當我們在遇到需要長時間執行的任務時候,比如讀取一個文件,遠程服務調用。這些功能都會阻塞主線程,造成主線程卡死,從而造成一種軟件崩潰的假象。這樣的情況下,我們都會想到使用異步多線程的技術去解決這個問題。
我在學習NodeJs的之前,一直以為異步和多線程是同一個概念,當我接觸到Node的時候,感覺自己遭到了當頭棒喝,Node是單線程的,也不支持多線程,但是他的很多操作都是異步的,比如文件的讀取。這讓我很沮喪,也花了很長時間去理解異步和多線程的概念區別,現在記錄下來我現在的想法,希望看到的朋友也能幫組我理解一下。
異步,相對於同步,C#執行代碼的順序是從上到下,從右到左,從上往下執行的這種就稱之為同步執行,異步相對於同步,就是同時執行的意思。
如下流程圖
如上圖是同步和異步的執行模式。
什么是多線程?多線程是實現異步的一種技術。綜上:異步是一種技術功能要求,多線程是實現異步的一種手段。除了使用多線程可以實現異步,異步I/O操作也能實現。硬盤,顯卡這些硬件是可以不消耗CPU資源而自動與內存交換數據的,這也是實現異步的基本條件,當數據交互完成,再觸發指定的回調函數,來實現異步之后的同步。所以這也是NodeJs的異步I/O操作全部是通過異步回調來實現的原因。
在Net中可以使用委托實現異步調用的功能。
Action test = () =>
{
for (double i = 0; i < 10000; i++)
{
Thread.Sleep(1);
}
Console.WriteLine("耗時操作結束!");
};
test.BeginInvoke(null, null);
Console.Write("程序執行結束!");
BeginInvoke就可以實現異步操作
BeginInvoke有兩個參數一個是AsyncCallback,一個是object,前一個參數是一個委托,看名字就知道是一個回調函數,當異步執行完成之后,就會執行回調函數,object代表一個參數,如果回調函數需要參數則通過object傳入。
如果不想通過回調函數,同時又想等待異步執行完成,那么可以通過EndInvoke來實現
Action test = () =>
{
int result = 0;
for (int i = 0; i < 1000; i++)
{
result += i;
Thread.Sleep(5);
}
};
test.BeginInvoke((state) =>
{
Console.WriteLine("傳入的參數是"+state.AsyncState);
}, "Test");
以上是帶回調函數的示例
Func<int> test = () =>
{
int r = 0;
for (int i = 0; i < 1000; i++)
{
r += i;
Thread.Sleep(3);
}
return r;
};
var re= test.BeginInvoke(null,null);
int result = test.EndInvoke(re);
以上會為了獲取運行結果的示例