委托之异步
在 使用BackgroundWorker組件 一文中,闡述了在Winform編程中,使用BackgroundWorker組件實現(xiàn)異步調用,本文主要講述利用委托實現(xiàn)異步。
以下描述摘抄于MSDN:
異步委托提供以異步方式調用同步方法的能力。
當同步調用委托時,Invoke()方法直接對當前線程調用目標方法;
當異步調用委托時,CLR將對請求進行排隊并立即返回到調用方,將對來自線程池的線程調用該目標方法,提交請求的原始線程繼續(xù)與目標方法并行執(zhí)行,該目標方法是對線程池線程運行的.
1)、BeginInvoke()方法
BeginInvoke()方法啟動異步調用,它與需要異步執(zhí)行的方法具有相同的參數(shù)。
另外,還有兩個可選參數(shù):第一個參數(shù)是AsyncCallback委托,該委托引用在異步調用完成時要調用的方法;第二個參數(shù)是用戶定義的對象,該對象可向回調方法傳遞信息;
BeginInvoke立即返回,不等待異步調用完成;
BeginInvoke返回IAsyncResult,這個結果可用于監(jiān)視異步調用的進度;
2)、EndInvoke()方法
EndInvoke()方法檢索異步調用的結果;
在調用BeginInvoke()方法后,可以隨時調用EndInvoke()方法,如果異步調用尚未完成,則EndInvoke()方法將一直阻止調用線程,直到異步調用完成后才允許調用線程執(zhí)行;
EndInvoke()的參數(shù)需要異步執(zhí)行的方法的out和ref參數(shù)以及由BeginInvoke()返回的IAsyncResult。
?
下面通過代碼闡述異步委托:
代碼一,同步執(zhí)行:
public delegate int MathDelegate(int x);public class MathClass
{
public int Add(int x)
{
Thread.Sleep(10000);//此處模擬長時間執(zhí)行的任務
return x + x;
}
}
public class Program
{
public static void Main(string[] args)
{
MathClass addClass = new MathClass();
MathDelegate mathDel = new MathDelegate(addClass.Add);
//同步執(zhí)行
int syncResult = mathDel(8);
Console.WriteLine("Sync Proccessing operation...");//這一行只有SyncMethod完成以后才能顯示
Console.WriteLine("Sync Result is: {0}", syncResult);
Console.ReadLine();
}
}
當程序執(zhí)行到 int syncResult = mathDel(8); 的時候,主線程將等待至少10秒的時間(Add方法的執(zhí)行),才能執(zhí)行后面的代碼,也即在期間,應用程序沒有響應,不能執(zhí)行其他的任何操作,直到Add方法返回結果。
代碼二,異步執(zhí)行:
我們稍微修改一下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 對象。
代碼三,IsCompleted,輪詢異步調用完成
使用IAsyncResult實例的IsCompleted屬性,以獲取異步操作是否已完成的指示,如果操作完成則為True,否則為False。
修改一下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,異步調用完成時執(zhí)行回調方法
如果啟動異步調用的線程不需要是處理結果的線程,則可以在調用完成時執(zhí)行回調方法;
如果要使用回調方法,必須將引用回調方法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)
{
AsyncResult ar = (AsyncResult)async;
MathDelegate del = (MathDelegate)ar.AsyncDelegate;
int result = del.EndInvoke(async);
string mainTheadMsg = ar.AsyncState as string;
Console.WriteLine("{0}, Result is: {1}", mainTheadMsg, result);
}Add方法調用完成以后,調用 CompleteMethod 方法
結束
轉載于:https://www.cnblogs.com/inforasc/archive/2009/10/21/1587756.html
總結
- 上一篇: C++ operator操作符重载(++
- 下一篇: ORACLE EXP/IMP 说明