以下描述摘抄於MSDN:
異步委托提供以異步方式調用同步方法的能力。
當同步調用委托時,Invoke()方法直接對當前線程調用目標方法;
當異步調用委托時,CLR將對請求進行排隊並立即返回到調用方,將對來自線程池的線程調用該目標方法,提交請求的原始線程繼續與目標方法並行執行,該目標方法是對線程池線程運行的.
1)、BeginInvoke()方法
BeginInvoke()方法啟動異步調用,它與需要異步執行的方法具有相同的參數。
另外,還有兩個可選參數:第一個參數是AsyncCallback委托,該委托引用在異步調用完成時要調用的方法;第二個參數是用戶定義的對象,該對象可向回調方法傳遞信息;
BeginInvoke立即返回,不等待異步調用完成;
BeginInvoke返回IAsyncResult,這個結果可用於監視異步調用的進度;
2)、EndInvoke()方法
EndInvoke()方法檢索異步調用的結果;
在調用BeginInvoke()方法後,可以隨時調用EndInvoke()方法,如果異步調用尚未完成,則EndInvoke()方法將一直阻止調用線程,直到異步調用完成後才允許調用線程執行;
EndInvoke()的參數需要異步執行的方法的out和ref參數以及由BeginInvoke()返回的IAsyncResult。
下面通過代碼闡述異步委托:
public delegate int MathDelegate(int x);
public class MathClass
{
public int Add(int x)
{
Thread.Sleep(10000);//此處模擬長時間執行的任務
return x + x;
}
}
public class Program
{
public static void Main(string[] args)
{
MathClass addClass = new MathClass();
MathDelegate mathDel = new MathDelegate(addClass.Add);
//同步執行
int syncResult = mathDel(8);
Console.WriteLine("Sync Proccessing operation...");//這一行只有SyncMethod完成以後才能顯示
Console.WriteLine("Sync Result is: {0}", syncResult);
Console.ReadLine();
}
}
當程序執行到 int syncResult = mathDel(8); 的時候,主線程將等待至少10秒的時間(Add方法的執行),才能執行
後面的代碼,也即在期間,應用程序沒有響應,不能執行其他的任何操作,直到Add方法返回結果。
我們稍微修改一下Main的代碼:
public static void Main(string[] args)
{
MathClass addClass = new MathClass();
MathDelegate mathDel = new MathDelegate(addClass.Add);
IAsyncResult async = mathDel.BeginInvoke(9, null, null);//在另外的線程裡,調用Add方法
Console.WriteLine("Async Proccessing operation...");//立即打印到終端設備
int asyncReuslt = mathDel.EndInvoke(async);
Console.WriteLine("Result is: {0}", asyncReuslt);
Console.ReadLine();
}
在這段代碼中,在開始並沒有直接調用方法,而是使用BeginInvoke()方法,返回IAsyncResult 對象。
修改一下Main的代碼:
public static void Main(string[] args)
{
MathClass addClass = new MathClass();
MathDelegate mathDel = new MathDelegate(addClass.Add);
IAsyncResult async = mathDel.BeginInvoke(9, null, null);//在另外的線程裡,調用Add方法
Console.WriteLine("Async Proccessing operation...");//立即打印到終端設備
int i = 1;
while (async.IsCompleted==false)
{
Thread.Sleep(i * 1000);
Console.WriteLine("IsCompleted:{0},{1}", async.IsCompleted, i);
i++;
}
int asyncReuslt = mathDel.EndInvoke(async);
Console.WriteLine("Result is: {0}", asyncReuslt);
Console.ReadLine();
}
如果啟動異步調用的線程不需要是處理結果的線程,則可以在調用完成時執行回調方法;
如果要使用回調方法,必須將引用回調方法AsyncCallback委托傳遞給BeginInvoke()方法,也可以傳遞包含回調方法將要使用的信息的對象。
修改一下Main的代碼:
public static void Main(string[] args)
{
MathClass addClass = new MathClass();
MathDelegate mathDel = new MathDelegate(addClass.Add);
IAsyncResult async = mathDel.BeginInvoke(9, new AsyncCallback(CompleteMethod), "信息來自於主線程");//在另外的線程裡,調用Add方法
Console.WriteLine("Async Proccessing operation...");//立即打印到終端設備
Console.ReadLine();
}
private static void CompleteMethod(IAsyncResult async)
{