C#可以有一個簡單易用的機制用於異步執行方法,那就是委托。下面我介紹三種模式,對於這三種模式來說,原始線程都發起了一個異步方法,然后做一些其他處理。然而這些模式不同的是,原始線程獲取發起的線程已經完成的消息的方式。
1:在等待一直到完成(wait-nutil-done)模式。
在發起了異步方法以及做了一些其他處理之后,原始線程就中斷並且等異步方法完成之后再繼續。
class Program
{
private delegate int MyDel(int a);
public static int MyMenthod(int a)
{
for (int i = 0; i < 1000; i++)
{
a++;
}
return a;
}
static void Main(string[] args)
{
var del = new MyDel(MyMenthod);
Console.WriteLine("Before BeginInvoke");
IAsyncResult iar = del.BeginInvoke(5, null, null);
Console.WriteLine("After BeginInvoke");
Console.WriteLine("Doing stuff");
long result = del.EndInvoke(iar);
Console.WriteLine("結果為{0}",result);
}
}
運行結果為

2:輪詢模式(polling)。
原始線程定期檢查發起的線程是否完成,如果沒有則可以繼續做其他的事情。上代碼
class Program
{
private delegate int MyDel(int a);
public static int MyMenthod(int a)
{
for (int i = 0; i < 1000; i++)
{
a++;
}
Thread.Sleep(3000);
return a;
}
static void Main(string[] args)
{
var del = new MyDel(MyMenthod);
IAsyncResult iar = del.BeginInvoke(5,null,null);
Console.WriteLine("After BeginInvoke");
while (!iar.IsCompleted)
{
Console.WriteLine("還沒處理完");
Thread.Sleep(2000);
Console.WriteLine("繼續處理其他事情");
}
Console.WriteLine("異步執行完成");
long result = del.EndInvoke(iar);
Console.WriteLine("結果為{0}",result);
}
}
運行結果為:

3:回調模式(callbacl)。
原始線程一直執行,無需等待或檢查發起的線程是否完成,在發起的線程中的引用方法完成之后,發起的線程就會調用回調方法,由回調方法在調用EndInvoke之前處理異步方法的結構。上代碼
class Program
{
private delegate int MyDel(int a);
public static int MyMenthod(int a)
{
for (int i = 0; i < 1000; i++)
{
a++;
}
return a;
}
public static void CallBack(IAsyncResult iar)
{
AsyncResult ar = iar as AsyncResult;
MyDel del = (MyDel)ar.AsyncDelegate;
long r = del.EndInvoke(iar);
Thread.Sleep(2000);
Console.WriteLine("結果出來了,為{0}", r);
}
static void Main(string[] args)
{
var del = new MyDel(MyMenthod);
Console.WriteLine("After BeginInvoke");
IAsyncResult iar= del.BeginInvoke(5, CallBack, del);
Console.WriteLine("Doing More Work In Main");
Thread.Sleep(5000);
}
}
運行結果為:

回調方法的簽名和返回類型必須和AsyncCallbacl委托類型所描述的形式一致。它需要方法接受一個IAsyncResult作為參數並且返回類型是void,如下:
void AsyncCallback(IAsyncResult iar)
我們有多種方式可以為BeginInvoke方法提供回調方法,由於BeginInvoke中的callback參數是AsyncCallback類型的委托,我們可以以委托形式提供,我們也可以只提供回調方法名稱,讓編譯器為我們創建委托,兩種形式是等價的。
IAsyncResult iar1 = del.BeginInvoke(5,new AsyncCallback(CallWhenDone),null);
IAsyncResult iar2 = del.BenginInvoke(5,CallWhenDone,null);
