本文參考自C#基礎:線程之異步回調(委托),純屬讀書筆記
在解析異步回調之前,先看同步回調的執行過程,以及代碼原理。
1、線程的同步執行
同步執行:在主線程執行的時候,主線程調用一個其它方法,此時主線程阻塞,等待調用方法執行完成后主線程才能繼續執行。

代碼如下:
class Program { static void Main(string[] args) { for (int i = 1; i < 11; i++) { if (i == 5) { Console.WriteLine("調用TakeAWhile方法並等待其執行完成"); Console.WriteLine("開始執行TakeAWhile方法,時間:{0}", DateTime.Now); int result = TakeAWhile(0, 6000); if (result == 1) { Console.WriteLine("TakeAWhile方法執行完成"); } Console.WriteLine("TakeAWhile方法執行完畢,時間:{0}", DateTime.Now); } Thread.Sleep(30); Console.WriteLine(i.ToString()); } } static int TakeAWhile(int data, int time) { Thread.Sleep(time); return ++data; } }

從上面的結果得出當程序開始調用TakeAWhile方法后,主線程阻塞,當TakeAWhile方法調用完畢之后,主線程又重新開始運行,這個過程就是線程的同步執行的過程.
2、線程的異步執行
what is 異步執行?
異步執行:在主線程執行的時候,打開一個子線程,主線程不會像同步執行的那樣等待子線程的結果返回后在執行,主線程會繼續執行,當主線程需要子線程的運行結果時,主線程直接調用子線程的運行結果,如果子線程的運行結果還沒有出來,那么主線程等待,直到子線程執行結束,主線程拿到子線程的運行結果,主線程在繼續。

class Program { static void Main(string[] args) { Func<int, int, int> fun = TakeAWhile; IAsyncResult ar = fun.BeginInvoke(0, 1000, null, null);//主線程調用子線程開始執行TakeAWhile方法,並給它傳遞了參數 int times=1; while (!ar.IsCompleted) { //當子線程沒有完成之前,主線程可以在該while語句塊內進行任何后續操作,而且不用等待子線程的結束 Console.WriteLine(times++); Thread.Sleep(50); } int result = fun.EndInvoke(ar);//1秒之后我需要子線程的結果了,ok,從子線程中拿到結果 Console.WriteLine("TakeAWhile方法結束,時間是:{0}", DateTime.Now); Console.WriteLine("result:{0}", result); Console.ReadKey(); } static int TakeAWhile(int data, int times) { Console.WriteLine("TakeAWhile方法開始執行,時間是:{0}",DateTime.Now); Thread.Sleep(times); return ++data; } }

從結果和代碼進行分析,當通過BeginInvoke方法開始異步執行TakeAWhile方法,主線程繼續執行,然后通過IsCompleted屬性判斷TakeAWhile是否執行完成,最后獲取子線程的輸出值,並輸出其結果,整個過程主線程沒有因為在執行子線程的原因,而造成阻塞
注:
因為多線程,導致了這個情況,開啟子線程和執行子線程中的方法都需要時間,所以主線程的執行速度快於子線程,所以先輸出了一個1;解決方法很簡單,讓主線程休息一會,等子線程先初始化完,代碼如下:
class Program { static void Main(string[] args) { Func<int, int, int> fun = TakeAWhile; IAsyncResult ar = fun.BeginInvoke(0, 1000, null, null);//主線程調用子線程開始執行TakeAWhile方法,並給它傳遞了參數 Thread.Sleep(30);//休息一會 int times=1; while (!ar.IsCompleted) { //當子線程沒有完成之前,主線程可以在該while語句塊內進行任何后續操作,而且不用等待子線程的結束 Console.WriteLine(times++); Thread.Sleep(50); } int result = fun.EndInvoke(ar);//6秒之后我需要子線程的結果了,ok,從子線程中拿到結果 Console.WriteLine("TakeAWhile方法結束,時間是:{0}", DateTime.Now); Console.WriteLine("result:{0}", result); Console.ReadKey(); } static int TakeAWhile(int data, int times) { Console.WriteLine("TakeAWhile方法開始執行,時間是:{0}",DateTime.Now); Thread.Sleep(times); return ++data; } }

3、異步回調
what is 異步異步回調?
異步回調:主線程在執行的時候,打開一個子線程,主線程繼續執行,當子線程執行完成的時候,主線程立即輸出子線程的運行結果,主線程繼續執行。
class Program { static void Main(string[] args) { Func<int, int, int> fun = TakeAWhile; fun.BeginInvoke(0, 1000, TakesAWhileCallBack, fun);//異步調用TakeAWhile,並指定回調函數TakesAWhileCallBack for (int i = 0; i < 20; i++) { Console.WriteLine(i.ToString()); Thread.Sleep(100); } Console.ReadKey(); } static int TakeAWhile(int data, int times) { Console.WriteLine("TakeAWhile方法開始執行,時間是:{0}", DateTime.Now); Thread.Sleep(times); return ++data; } /// <summary> /// 回調函數 /// </summary> /// <param name="fun">調用的委托</param> static void TakesAWhileCallBack(IAsyncResult fun) { if (fun == null) throw new ArgumentNullException("fun"); Func<int, int, int> dl = (Func<int, int, int>)fun.AsyncState; int result = dl.EndInvoke(fun); Console.WriteLine("我是回調函數返回的結果:{0}", result); Console.WriteLine("TakeAWhile執行完成,時間是:{0}", DateTime.Now); } }

