程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> 委托之異步

委托之異步

編輯:C#入門知識

以下描述摘抄於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 對象。

代碼三,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,異步調用完成時執行回調方法

如果啟動異步調用的線程不需要是處理結果的線程,則可以在調用完成時執行回調方法;

如果要使用回調方法,必須將引用回調方法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)
{
  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved