在上一篇文章(什麼是.Net的異步機制(Invoke,BeginInvoke,EndInvoke) - step 2 ), 我們已經簡單介紹了異步的調用方式, 下面我們來看看異步的核心.
異步的核心: IAsyncResult
Asynchronous Programming Model
整個異步調用過程中都是圍繞IAsyncResult來進行的,大家可以看看上篇文章的例子,BeginXXX 傳回這個對象,EndXXX接收這個對象來結束目前異步對象,下面我們來看看IAsyncResult 接口成員/和實作此接口的AsyncResult類成員(其中有些在上篇中已經涉及到)
IAsyncResult接口
1
.Net的異步機制(APM核心:IAsyncResult) - step 3 public interface IAsyncResult
2
.Net的異步機制(APM核心:IAsyncResult) - step 3
.Net的異步機制(APM核心:IAsyncResult) - step 3
.Net的異步機制(APM核心:IAsyncResult) - step 3 {
3
.Net的異步機制(APM核心:IAsyncResult) - step 3
.Net的異步機制(APM核心:IAsyncResult) - step 3 WaitHandle AsyncWaitHandle
.Net的異步機制(APM核心:IAsyncResult) - step 3 { get; } //阻塞一個線程,直到一個或多個同步對象接收到信号
4
.Net的異步機制(APM核心:IAsyncResult) - step 3
.Net的異步機制(APM核心:IAsyncResult) - step 3 Boolean IsCompleted
.Net的異步機制(APM核心:IAsyncResult) - step 3 { get; } //判讀目前異步是否完成
5
.Net的異步機制(APM核心:IAsyncResult) - step 3
.Net的異步機制(APM核心:IAsyncResult) - step 3 Object AsyncState
.Net的異步機制(APM核心:IAsyncResult) - step 3 { get; } //擷取額外的參數值,請看上一篇文章的Code 4.3
6
.Net的異步機制(APM核心:IAsyncResult) - step 3
.Net的異步機制(APM核心:IAsyncResult) - step 3 Boolean CompletedSynchronously
.Net的異步機制(APM核心:IAsyncResult) - step 3 { get; } //幾乎沒有使用
7
.Net的異步機制(APM核心:IAsyncResult) - step 3 }
AsyncResult類
1
.Net的異步機制(APM核心:IAsyncResult) - step 3 public class AsyncResult : IAsyncResult, IMessageSink
2
.Net的異步機制(APM核心:IAsyncResult) - step 3
.Net的異步機制(APM核心:IAsyncResult) - step 3
.Net的異步機制(APM核心:IAsyncResult) - step 3 {
3
.Net的異步機制(APM核心:IAsyncResult) - step 3 //IAsyncResult 的實作
4
.Net的異步機制(APM核心:IAsyncResult) - step 3
.Net的異步機制(APM核心:IAsyncResult) - step 3 public virtual WaitHandle AsyncWaitHandle
.Net的異步機制(APM核心:IAsyncResult) - step 3 { get; }
5
.Net的異步機制(APM核心:IAsyncResult) - step 3
.Net的異步機制(APM核心:IAsyncResult) - step 3 public virtual bool IsCompleted
.Net的異步機制(APM核心:IAsyncResult) - step 3 { get; }
6
.Net的異步機制(APM核心:IAsyncResult) - step 3
.Net的異步機制(APM核心:IAsyncResult) - step 3 public virtual object AsyncState
.Net的異步機制(APM核心:IAsyncResult) - step 3 { get; }
7
.Net的異步機制(APM核心:IAsyncResult) - step 3
.Net的異步機制(APM核心:IAsyncResult) - step 3 public virtual bool CompletedSynchronously
.Net的異步機制(APM核心:IAsyncResult) - step 3 { get; }
8
.Net的異步機制(APM核心:IAsyncResult) - step 3 9
.Net的異步機制(APM核心:IAsyncResult) - step 3 // 其他一些重要的屬性
10
.Net的異步機制(APM核心:IAsyncResult) - step 3
.Net的異步機制(APM核心:IAsyncResult) - step 3 public bool EndInvokeCalled
.Net的異步機制(APM核心:IAsyncResult) - step 3 { get; set; } //檢驗是否調用了EndInvoke()
11
.Net的異步機制(APM核心:IAsyncResult) - step 3
.Net的異步機制(APM核心:IAsyncResult) - step 3 public virtual object AsyncDelegate
.Net的異步機制(APM核心:IAsyncResult) - step 3 { get; } //擷取原始的委托對象,可檢視上一篇文章中的Code 4.1/4.2/5
12
.Net的異步機制(APM核心:IAsyncResult) - step 3 }
注意:基本上都是隻讀屬性
下面我們來看看異步的執行順序,并回顧下 IAsyncResult 下各個屬性的應用,如果還是不熟悉請看前2篇文章.
Code 1:
1
.Net的異步機制(APM核心:IAsyncResult) - step 3 class Program
2
.Net的異步機制(APM核心:IAsyncResult) - step 3
.Net的異步機制(APM核心:IAsyncResult) - step 3
.Net的異步機制(APM核心:IAsyncResult) - step 3 {
3
.Net的異步機制(APM核心:IAsyncResult) - step 3 static void Main(string[] args)
4
.Net的異步機制(APM核心:IAsyncResult) - step 3
.Net的異步機制(APM核心:IAsyncResult) - step 3
.Net的異步機制(APM核心:IAsyncResult) - step 3 {
5
.Net的異步機制(APM核心:IAsyncResult) - step 3 Console.WriteLine("[(#{1}){0}]:Asynchronous Start", DateTime.Now.ToString(), Thread.CurrentThread.ManagedThreadId);
6
.Net的異步機制(APM核心:IAsyncResult) - step 3 7
.Net的異步機制(APM核心:IAsyncResult) - step 3 AsyncTest test = new AsyncTest();
8
.Net的異步機制(APM核心:IAsyncResult) - step 3 MyThirdAsyncCode.AsyncTest.SalaryEventHandler del = test.YearlySalary;
9
.Net的異步機制(APM核心:IAsyncResult) - step 3 //使用回調函數
10
.Net的異步機制(APM核心:IAsyncResult) - step 3 AsyncCallback callback = new AsyncCallback(OnSalaryCallback);
11
.Net的異步機制(APM核心:IAsyncResult) - step 3 IAsyncResult ar = del.BeginInvoke(100000, 15, 100000, callback, 2000);
12
.Net的異步機制(APM核心:IAsyncResult) - step 3 13
.Net的異步機制(APM核心:IAsyncResult) - step 3 DoAntherJob();
14
.Net的異步機制(APM核心:IAsyncResult) - step 3 Console.ReadLine(); // 讓黑屏等待,不會直接關閉..
15
.Net的異步機制(APM核心:IAsyncResult) - step 3 }
16
.Net的異步機制(APM核心:IAsyncResult) - step 3 17
.Net的異步機制(APM核心:IAsyncResult) - step 3 //開始其他工作.
18
.Net的異步機制(APM核心:IAsyncResult) - step 3 static void DoAntherJob()
19
.Net的異步機制(APM核心:IAsyncResult) - step 3
.Net的異步機制(APM核心:IAsyncResult) - step 3
.Net的異步機制(APM核心:IAsyncResult) - step 3 {
20
.Net的異步機制(APM核心:IAsyncResult) - step 3 Thread.Sleep(1000);//需要1秒才能完成這個工作,注1
21
.Net的異步機制(APM核心:IAsyncResult) - step 3 Console.WriteLine("[(#{1}){0}]:Do Another Job", DateTime.Now.ToString(), Thread.CurrentThread.ManagedThreadId);
22
.Net的異步機制(APM核心:IAsyncResult) - step 3 }
23
.Net的異步機制(APM核心:IAsyncResult) - step 3 24
.Net的異步機制(APM核心:IAsyncResult) - step 3 static void OnSalaryCallback(IAsyncResult asyncResult)
25
.Net的異步機制(APM核心:IAsyncResult) - step 3
.Net的異步機制(APM核心:IAsyncResult) - step 3
.Net的異步機制(APM核心:IAsyncResult) - step 3 {
26
.Net的異步機制(APM核心:IAsyncResult) - step 3 //通過AsyncState 擷取額外的參數.
27
.Net的異步機制(APM核心:IAsyncResult) - step 3 decimal para = (int)asyncResult.AsyncState;
28
.Net的異步機制(APM核心:IAsyncResult) - step 3 29
.Net的異步機制(APM核心:IAsyncResult) - step 3 //通過AsyncDelegate 擷取原始的委托對象
30
.Net的異步機制(APM核心:IAsyncResult) - step 3 AsyncResult obj = (AsyncResult)asyncResult;
31
.Net的異步機制(APM核心:IAsyncResult) - step 3 MyThirdAsyncCode.AsyncTest.SalaryEventHandler del =
(MyThirdAsyncCode.AsyncTest.SalaryEventHandler)obj.AsyncDelegate;
32
.Net的異步機制(APM核心:IAsyncResult) - step 3 33
.Net的異步機制(APM核心:IAsyncResult) - step 3 if (asyncResult.IsCompleted)// 判讀是否已經調用完成
34
.Net的異步機制(APM核心:IAsyncResult) - step 3 Console.WriteLine("[(#{1}){0}]:Asynchronous Finished.", DateTime.Now.ToString(), Thread.CurrentThread.ManagedThreadId);
35
.Net的異步機制(APM核心:IAsyncResult) - step 3 36
.Net的異步機制(APM核心:IAsyncResult) - step 3 decimal val = del.EndInvoke(asyncResult);
37
.Net的異步機制(APM核心:IAsyncResult) - step 3 38
.Net的異步機制(APM核心:IAsyncResult) - step 3 Console.WriteLine("[(#{2}){0}]:Output Result:{1}", DateTime.Now.ToString(), val + para, Thread.CurrentThread.ManagedThreadId);
39
.Net的異步機制(APM核心:IAsyncResult) - step 3 }
40
.Net的異步機制(APM核心:IAsyncResult) - step 3 }
41
.Net的異步機制(APM核心:IAsyncResult) - step 3 42
.Net的異步機制(APM核心:IAsyncResult) - step 3 public class AsyncTest
43
.Net的異步機制(APM核心:IAsyncResult) - step 3
.Net的異步機制(APM核心:IAsyncResult) - step 3
.Net的異步機制(APM核心:IAsyncResult) - step 3 {
44
.Net的異步機制(APM核心:IAsyncResult) - step 3 public delegate decimal SalaryEventHandler(decimal salary, int monthCount, decimal bonus); // 對應YearlySalary方法
45
.Net的異步機制(APM核心:IAsyncResult) - step 3 public decimal YearlySalary(decimal salary, int monthCount, decimal bonus)
46
.Net的異步機制(APM核心:IAsyncResult) - step 3
.Net的異步機制(APM核心:IAsyncResult) - step 3
.Net的異步機制(APM核心:IAsyncResult) - step 3 {
47
.Net的異步機制(APM核心:IAsyncResult) - step 3 //模拟耗時/複雜的邏輯計算.
48
.Net的異步機制(APM核心:IAsyncResult) - step 3 Thread.Sleep(3000);//等待3秒,注2
49
.Net的異步機制(APM核心:IAsyncResult) - step 3 return salary * monthCount + bonus;
50
.Net的異步機制(APM核心:IAsyncResult) - step 3 }
51
.Net的異步機制(APM核心:IAsyncResult) - step 3 }
.Net的異步機制(APM核心:IAsyncResult) - step 3 圖1
我們看到DoAntherJob 比異步YearlySalary快2秒,看代碼中(注1)和(注2),兩個線程的執行結果
接下來,我們說說AsyncWaitHandle 屬性. 他傳回WaitHandle對象(System.Threading.WaitHandle), 他有3個重要的方法. WaitOne / WaitAny / WaitAll ,我們先來說下WaitOne,在Code1代碼基礎上隻是增加了下面紅色部分.
1,WaitOne
Code 1.1
IAsyncResult ar = del.BeginInvoke(100000, 15, 100000, callback, 2000);
//阻礙目前線程,直到異步調用結束.
ar.AsyncWaitHandle.WaitOne();
//開始其他工作.
DoAntherJob();
.Net的異步機制(APM核心:IAsyncResult) - step 3 圖1.1
執行輸出,對比圖1我們可以看到執行的次序不一樣了(看時間),調用WaitOne,會阻礙目前線程,直到異步完成,才釋放目前的線程, WaitOne 提供了時間的重載版本WaitOne(int millisecondsTimeout)/ WaitOne(TimeSpan timeout);來判斷阻礙的時間.無參的版本是無限等待的(直到異步調用結束)
2, WaitAll
我們在Code1的代碼基礎上加上Hello的異步調用(使Main提供多個異步調用),注意紅色部分.
Code 1.2
1
.Net的異步機制(APM核心:IAsyncResult) - step 3 class Program
2
.Net的異步機制(APM核心:IAsyncResult) - step 3
.Net的異步機制(APM核心:IAsyncResult) - step 3
.Net的異步機制(APM核心:IAsyncResult) - step 3 {
3
.Net的異步機制(APM核心:IAsyncResult) - step 3 static void Main(string[] args)
4
.Net的異步機制(APM核心:IAsyncResult) - step 3
.Net的異步機制(APM核心:IAsyncResult) - step 3
.Net的異步機制(APM核心:IAsyncResult) - step 3 {
5
.Net的異步機制(APM核心:IAsyncResult) - step 3 Console.WriteLine("[(#{1}){0}]:Asynchronous Start", DateTime.Now.ToString(), Thread.CurrentThread.ManagedThreadId);
6
.Net的異步機制(APM核心:IAsyncResult) - step 3 7
.Net的異步機制(APM核心:IAsyncResult) - step 3 AsyncTest test = new AsyncTest();
8
.Net的異步機制(APM核心:IAsyncResult) - step 3 MyThirdAsyncCode.AsyncTest.SalaryEventHandler del = test.YearlySalary;
9
.Net的異步機制(APM核心:IAsyncResult) - step 3 MyThirdAsyncCode.AsyncTest.AsyncEventHandler asy = test.Hello;
10
.Net的異步機制(APM核心:IAsyncResult) - step 3 11
.Net的異步機制(APM核心:IAsyncResult) - step 3 IAsyncResult salayAsyc = del.BeginInvoke(100000, 15, 100000, OnSalaryCallback, null);
12
.Net的異步機制(APM核心:IAsyncResult) - step 3 IAsyncResult helloAsyc = asy.BeginInvoke("Hello Andy", OnHelloCallback, null);
13
.Net的異步機制(APM核心:IAsyncResult) - step 3 //把所有異步的句柄儲存到WaitHandle 對象中
14
.Net的異步機制(APM核心:IAsyncResult) - step 3
.Net的異步機制(APM核心:IAsyncResult) - step 3 WaitHandle[] handles =
.Net的異步機制(APM核心:IAsyncResult) - step 3 { salayAsyc.AsyncWaitHandle, helloAsyc.AsyncWaitHandle };
15
.Net的異步機制(APM核心:IAsyncResult) - step 3 //阻礙目前線程,直到所有異步調用結束.
16
.Net的異步機制(APM核心:IAsyncResult) - step 3 WaitHandle.WaitAll(handles);
17
.Net的異步機制(APM核心:IAsyncResult) - step 3 18
.Net的異步機制(APM核心:IAsyncResult) - step 3 //開始其他工作.
19
.Net的異步機制(APM核心:IAsyncResult) - step 3 DoAntherJob();
20
.Net的異步機制(APM核心:IAsyncResult) - step 3 Console.ReadLine(); // 讓黑屏等待,不會直接關閉..
21
.Net的異步機制(APM核心:IAsyncResult) - step 3 }
22
.Net的異步機制(APM核心:IAsyncResult) - step 3 static void DoAntherJob()
23
.Net的異步機制(APM核心:IAsyncResult) - step 3
.Net的異步機制(APM核心:IAsyncResult) - step 3
.Net的異步機制(APM核心:IAsyncResult) - step 3 {
24
.Net的異步機制(APM核心:IAsyncResult) - step 3 Thread.Sleep(1000);//需要1秒才能完成這個工作,注1
25
.Net的異步機制(APM核心:IAsyncResult) - step 3 Console.WriteLine("[(#{1}){0}]:Do Another Job", DateTime.Now.ToString(), Thread.CurrentThread.ManagedThreadId);
26
.Net的異步機制(APM核心:IAsyncResult) - step 3 }
27
.Net的異步機制(APM核心:IAsyncResult) - step 3 static void OnSalaryCallback(IAsyncResult asyncResult)
28
.Net的異步機制(APM核心:IAsyncResult) - step 3
.Net的異步機制(APM核心:IAsyncResult) - step 3
.Net的異步機制(APM核心:IAsyncResult) - step 3 {
29
.Net的異步機制(APM核心:IAsyncResult) - step 3 //通過AsyncDelegate 擷取原始的委托對象
30
.Net的異步機制(APM核心:IAsyncResult) - step 3 AsyncResult obj = (AsyncResult)asyncResult;
31
.Net的異步機制(APM核心:IAsyncResult) - step 3 MyThirdAsyncCode.AsyncTest.SalaryEventHandler del =
(MyThirdAsyncCode.AsyncTest.SalaryEventHandler)obj.AsyncDelegate;
32
.Net的異步機制(APM核心:IAsyncResult) - step 3 33
.Net的異步機制(APM核心:IAsyncResult) - step 3 if (asyncResult.IsCompleted)// 判讀是否已經調用完成
34
.Net的異步機制(APM核心:IAsyncResult) - step 3 Console.WriteLine("[(#{1}){0}]:Asynchronous Finished.", DateTime.Now.ToString(), Thread.CurrentThread.ManagedThreadId);
35
.Net的異步機制(APM核心:IAsyncResult) - step 3 36
.Net的異步機制(APM核心:IAsyncResult) - step 3 decimal val = del.EndInvoke(asyncResult);
37
.Net的異步機制(APM核心:IAsyncResult) - step 3 Console.WriteLine("[(#{2}){0}]:Output Result:{1}", DateTime.Now.ToString(), val, Thread.CurrentThread.ManagedThreadId);
38
.Net的異步機制(APM核心:IAsyncResult) - step 3 }
39
.Net的異步機制(APM核心:IAsyncResult) - step 3 40
.Net的異步機制(APM核心:IAsyncResult) - step 3 static void OnHelloCallback(IAsyncResult asyncResult)
41
.Net的異步機制(APM核心:IAsyncResult) - step 3
.Net的異步機制(APM核心:IAsyncResult) - step 3
.Net的異步機制(APM核心:IAsyncResult) - step 3 {
42
.Net的異步機制(APM核心:IAsyncResult) - step 3 //通過AsyncDelegate 擷取原始的委托對象
43
.Net的異步機制(APM核心:IAsyncResult) - step 3 AsyncResult obj = (AsyncResult)asyncResult;
44
.Net的異步機制(APM核心:IAsyncResult) - step 3 MyThirdAsyncCode.AsyncTest.AsyncEventHandler del =
(MyThirdAsyncCode.AsyncTest.AsyncEventHandler)obj.AsyncDelegate;
45
.Net的異步機制(APM核心:IAsyncResult) - step 3 46
.Net的異步機制(APM核心:IAsyncResult) - step 3 if (asyncResult.IsCompleted)// 判讀是否已經調用完成
47
.Net的異步機制(APM核心:IAsyncResult) - step 3 Console.WriteLine("[(#{1}){0}]:Asynchronous Finished.", DateTime.Now.ToString(), Thread.CurrentThread.ManagedThreadId);
48
.Net的異步機制(APM核心:IAsyncResult) - step 3 49
.Net的異步機制(APM核心:IAsyncResult) - step 3 string val = del.EndInvoke(asyncResult);
50
.Net的異步機制(APM核心:IAsyncResult) - step 3 Console.WriteLine("[(#{2}){0}]:Output Result:{1}", DateTime.Now.ToString(), val, Thread.CurrentThread.ManagedThreadId);
51
.Net的異步機制(APM核心:IAsyncResult) - step 3 }
52
.Net的異步機制(APM核心:IAsyncResult) - step 3 }
53
.Net的異步機制(APM核心:IAsyncResult) - step 3 54
.Net的異步機制(APM核心:IAsyncResult) - step 3 public class AsyncTest
55
.Net的異步機制(APM核心:IAsyncResult) - step 3
.Net的異步機制(APM核心:IAsyncResult) - step 3
.Net的異步機制(APM核心:IAsyncResult) - step 3 {
56
.Net的異步機制(APM核心:IAsyncResult) - step 3 public delegate decimal SalaryEventHandler(decimal salary, int monthCount, decimal bonus); // 對應YearlySalary方法
57
.Net的異步機制(APM核心:IAsyncResult) - step 3 public delegate string AsyncEventHandler(string name); // 對應Hello 方法
58
.Net的異步機制(APM核心:IAsyncResult) - step 3 public string Hello(string name)
59
.Net的異步機制(APM核心:IAsyncResult) - step 3
.Net的異步機制(APM核心:IAsyncResult) - step 3
.Net的異步機制(APM核心:IAsyncResult) - step 3 {
60
.Net的異步機制(APM核心:IAsyncResult) - step 3 //模拟耗時/複雜的邏輯計算.等待5秒
61
.Net的異步機制(APM核心:IAsyncResult) - step 3 Thread.Sleep(5000);
62
.Net的異步機制(APM核心:IAsyncResult) - step 3 return "Hello:" + name;
63
.Net的異步機制(APM核心:IAsyncResult) - step 3 }
64
.Net的異步機制(APM核心:IAsyncResult) - step 3 public decimal YearlySalary(decimal salary, int monthCount, decimal bonus)
65
.Net的異步機制(APM核心:IAsyncResult) - step 3
.Net的異步機制(APM核心:IAsyncResult) - step 3
.Net的異步機制(APM核心:IAsyncResult) - step 3 {
66
.Net的異步機制(APM核心:IAsyncResult) - step 3 //模拟耗時/複雜的邏輯計算.
67
.Net的異步機制(APM核心:IAsyncResult) - step 3 Thread.Sleep(3000);//等待3秒
68
.Net的異步機制(APM核心:IAsyncResult) - step 3 return salary * monthCount + bonus;
69
.Net的異步機制(APM核心:IAsyncResult) - step 3 }
70
.Net的異步機制(APM核心:IAsyncResult) - step 3 }
.Net的異步機制(APM核心:IAsyncResult) - step 3 圖1.2
從圖1.2中可以看出,WaitAll會阻礙目前線程(主線程#10),等待所有異步的對象都執行完畢(耗時最長的異步),才釋放目前的線程,WaitAll/WaitAny的重載版本和WaitOne一樣.
3, WaitAny
和WaitAll 基本上是一樣的.我們可以使用 WaitAny 來指定某個/某幾個委托先等待,修改Code1.2紅色部分,使用WaitAny.
Code1.3
//把salayAsyc異步的句柄儲存到WaitHandle 對象中
WaitHandle[] handles = { salayAsyc.AsyncWaitHandle };
//阻礙目前線程,直到所有異步調用結束.
WaitHandle.WaitAny(handles);
.Net的異步機制(APM核心:IAsyncResult) - step 3 圖1.3
我們阻礙了DoAntherJob(#10)線程,直到Salary異步調用計算完成.同樣我們可以巧用這三個方法來改變我們方法執行的順序.
釋放資源
Code2
1
.Net的異步機制(APM核心:IAsyncResult) - step 3 static void OnSalaryCallback(IAsyncResult asyncResult)
2
.Net的異步機制(APM核心:IAsyncResult) - step 3
.Net的異步機制(APM核心:IAsyncResult) - step 3
.Net的異步機制(APM核心:IAsyncResult) - step 3 {
3
.Net的異步機制(APM核心:IAsyncResult) - step 3 //通過AsyncDelegate 擷取原始的委托對象
4
.Net的異步機制(APM核心:IAsyncResult) - step 3 AsyncResult obj = (AsyncResult)asyncResult;
5
.Net的異步機制(APM核心:IAsyncResult) - step 3 MyThirdAsyncCode.AsyncTest.SalaryEventHandler del =
(MyThirdAsyncCode.AsyncTest.SalaryEventHandler)obj.AsyncDelegate;
6
.Net的異步機制(APM核心:IAsyncResult) - step 3 7
.Net的異步機制(APM核心:IAsyncResult) - step 3 decimal val = del.EndInvoke(asyncResult);
8
.Net的異步機制(APM核心:IAsyncResult) - step 3 asyncResult.AsyncWaitHandle.Close();//顯示的釋放資源
9
.Net的異步機制(APM核心:IAsyncResult) - step 3 }
當開始調用BeginXXX後,就會建立一個新的AsyncResult對象.這個對象會構造一個WaitHandle句柄(通過AsyncWaitHandle通路),當我們EndXXX後,并不會馬上關閉這個句柄,而是等待垃圾收集器來關閉,這時候我們最後在調用EndXXX完成後,顯示的關閉這個句柄.
說到這裡,我們基本上把異步方法都解釋一遍,下面我們來看看重構的異步對象,我們也可以細細體會異步對象的内部執行代碼..下面Code3.1/3.2/3.3代碼來自Jeffery Richard大師的Power Threading類庫,具體可檢視http://msdn.microsoft.com/en-us/magazine/cc163467.aspx
重構的異步對象
1步,構造一個内部無參的AsyncResultNoResult對象,繼承IAsyncResult接口(保留原創的注釋)
Code3.1
1
.Net的異步機制(APM核心:IAsyncResult) - step 3 internal class AsyncResultNoResult : IAsyncResult
2
.Net的異步機制(APM核心:IAsyncResult) - step 3
.Net的異步機制(APM核心:IAsyncResult) - step 3
.Net的異步機制(APM核心:IAsyncResult) - step 3 {
3
.Net的異步機制(APM核心:IAsyncResult) - step 3 // Fields set at construction which never change while
4
.Net的異步機制(APM核心:IAsyncResult) - step 3 // operation is pending
5
.Net的異步機制(APM核心:IAsyncResult) - step 3 private readonly AsyncCallback m_AsyncCallback;
6
.Net的異步機制(APM核心:IAsyncResult) - step 3 private readonly Object m_AsyncState;
7
.Net的異步機制(APM核心:IAsyncResult) - step 3 8
.Net的異步機制(APM核心:IAsyncResult) - step 3 // Fields set at construction which do change after
9
.Net的異步機制(APM核心:IAsyncResult) - step 3 // operation completes
10
.Net的異步機制(APM核心:IAsyncResult) - step 3 private const Int32 c_StatePending = 0;
11
.Net的異步機制(APM核心:IAsyncResult) - step 3 private const Int32 c_StateCompletedSynchronously = 1;
12
.Net的異步機制(APM核心:IAsyncResult) - step 3 private const Int32 c_StateCompletedAsynchronously = 2;
13
.Net的異步機制(APM核心:IAsyncResult) - step 3 private Int32 m_CompletedState = c_StatePending;
14
.Net的異步機制(APM核心:IAsyncResult) - step 3 15
.Net的異步機制(APM核心:IAsyncResult) - step 3 // Field that may or may not get set depending on usage
16
.Net的異步機制(APM核心:IAsyncResult) - step 3 private ManualResetEvent m_AsyncWaitHandle;
17
.Net的異步機制(APM核心:IAsyncResult) - step 3 18
.Net的異步機制(APM核心:IAsyncResult) - step 3 // Fields set when operation completes
19
.Net的異步機制(APM核心:IAsyncResult) - step 3 private Exception m_exception;
20
.Net的異步機制(APM核心:IAsyncResult) - step 3 21
.Net的異步機制(APM核心:IAsyncResult) - step 3 public AsyncResultNoResult(AsyncCallback asyncCallback, Object state)
22
.Net的異步機制(APM核心:IAsyncResult) - step 3
.Net的異步機制(APM核心:IAsyncResult) - step 3
.Net的異步機制(APM核心:IAsyncResult) - step 3 {
23
.Net的異步機制(APM核心:IAsyncResult) - step 3 m_AsyncCallback = asyncCallback;
24
.Net的異步機制(APM核心:IAsyncResult) - step 3 m_AsyncState = state;
25
.Net的異步機制(APM核心:IAsyncResult) - step 3 }
26
.Net的異步機制(APM核心:IAsyncResult) - step 3 27
.Net的異步機制(APM核心:IAsyncResult) - step 3 public void SetAsCompleted(
28
.Net的異步機制(APM核心:IAsyncResult) - step 3 Exception exception, Boolean completedSynchronously)
29
.Net的異步機制(APM核心:IAsyncResult) - step 3
.Net的異步機制(APM核心:IAsyncResult) - step 3
.Net的異步機制(APM核心:IAsyncResult) - step 3 {
30
.Net的異步機制(APM核心:IAsyncResult) - step 3 // Passing null for exception means no error occurred.
31
.Net的異步機制(APM核心:IAsyncResult) - step 3 // This is the common case
32
.Net的異步機制(APM核心:IAsyncResult) - step 3 m_exception = exception;
33
.Net的異步機制(APM核心:IAsyncResult) - step 3 34
.Net的異步機制(APM核心:IAsyncResult) - step 3 // The m_CompletedState field MUST be set prior calling the callback
35
.Net的異步機制(APM核心:IAsyncResult) - step 3 Int32 prevState = Interlocked.Exchange(ref m_CompletedState,
36
.Net的異步機制(APM核心:IAsyncResult) - step 3 completedSynchronously ? c_StateCompletedSynchronously :
37
.Net的異步機制(APM核心:IAsyncResult) - step 3 c_StateCompletedAsynchronously);
38
.Net的異步機制(APM核心:IAsyncResult) - step 3 if (prevState != c_StatePending)
39
.Net的異步機制(APM核心:IAsyncResult) - step 3 throw new InvalidOperationException(
40
.Net的異步機制(APM核心:IAsyncResult) - step 3 "You can set a result only once");
41
.Net的異步機制(APM核心:IAsyncResult) - step 3 42
.Net的異步機制(APM核心:IAsyncResult) - step 3 // If the event exists, set it
43
.Net的異步機制(APM核心:IAsyncResult) - step 3 if (m_AsyncWaitHandle != null) m_AsyncWaitHandle.Set();
44
.Net的異步機制(APM核心:IAsyncResult) - step 3 45
.Net的異步機制(APM核心:IAsyncResult) - step 3 // If a callback method was set, call it
46
.Net的異步機制(APM核心:IAsyncResult) - step 3 if (m_AsyncCallback != null) m_AsyncCallback(this);
47
.Net的異步機制(APM核心:IAsyncResult) - step 3 }
48
.Net的異步機制(APM核心:IAsyncResult) - step 3 49
.Net的異步機制(APM核心:IAsyncResult) - step 3 public void EndInvoke()
50
.Net的異步機制(APM核心:IAsyncResult) - step 3
.Net的異步機制(APM核心:IAsyncResult) - step 3
.Net的異步機制(APM核心:IAsyncResult) - step 3 {
51
.Net的異步機制(APM核心:IAsyncResult) - step 3 // This method assumes that only 1 thread calls EndInvoke
52
.Net的異步機制(APM核心:IAsyncResult) - step 3 // for this object
53
.Net的異步機制(APM核心:IAsyncResult) - step 3 if (!IsCompleted)
54
.Net的異步機制(APM核心:IAsyncResult) - step 3
.Net的異步機制(APM核心:IAsyncResult) - step 3
.Net的異步機制(APM核心:IAsyncResult) - step 3 {
55
.Net的異步機制(APM核心:IAsyncResult) - step 3 // If the operation isn't done, wait for it
56
.Net的異步機制(APM核心:IAsyncResult) - step 3 AsyncWaitHandle.WaitOne();
57
.Net的異步機制(APM核心:IAsyncResult) - step 3 AsyncWaitHandle.Close();
58
.Net的異步機制(APM核心:IAsyncResult) - step 3 m_AsyncWaitHandle = null; // Allow early GC
59
.Net的異步機制(APM核心:IAsyncResult) - step 3 }
60
.Net的異步機制(APM核心:IAsyncResult) - step 3 61
.Net的異步機制(APM核心:IAsyncResult) - step 3 // Operation is done: if an exception occured, throw it
62
.Net的異步機制(APM核心:IAsyncResult) - step 3 if (m_exception != null) throw m_exception;
63
.Net的異步機制(APM核心:IAsyncResult) - step 3 }
64
.Net的異步機制(APM核心:IAsyncResult) - step 3 65
.Net的異步機制(APM核心:IAsyncResult) - step 3
.Net的異步機制(APM核心:IAsyncResult) - step 3 Implementation of IAsyncResult#region Implementation of IAsyncResult
66
.Net的異步機制(APM核心:IAsyncResult) - step 3
.Net的異步機制(APM核心:IAsyncResult) - step 3 public Object AsyncState
.Net的異步機制(APM核心:IAsyncResult) - step 3 { get
.Net的異步機制(APM核心:IAsyncResult) - step 3 { return m_AsyncState; } }
67
.Net的異步機制(APM核心:IAsyncResult) - step 3 68
.Net的異步機制(APM核心:IAsyncResult) - step 3 public Boolean CompletedSynchronously
69
.Net的異步機制(APM核心:IAsyncResult) - step 3
.Net的異步機制(APM核心:IAsyncResult) - step 3
.Net的異步機制(APM核心:IAsyncResult) - step 3 {
70
.Net的異步機制(APM核心:IAsyncResult) - step 3 get
71
.Net的異步機制(APM核心:IAsyncResult) - step 3
.Net的異步機制(APM核心:IAsyncResult) - step 3
.Net的異步機制(APM核心:IAsyncResult) - step 3 {
72
.Net的異步機制(APM核心:IAsyncResult) - step 3 return Thread.VolatileRead(ref m_CompletedState) ==
73
.Net的異步機制(APM核心:IAsyncResult) - step 3 c_StateCompletedSynchronously;
74
.Net的異步機制(APM核心:IAsyncResult) - step 3 }
75
.Net的異步機制(APM核心:IAsyncResult) - step 3 }
76
.Net的異步機制(APM核心:IAsyncResult) - step 3 77
.Net的異步機制(APM核心:IAsyncResult) - step 3 public WaitHandle AsyncWaitHandle
78
.Net的異步機制(APM核心:IAsyncResult) - step 3
.Net的異步機制(APM核心:IAsyncResult) - step 3
.Net的異步機制(APM核心:IAsyncResult) - step 3 {
79
.Net的異步機制(APM核心:IAsyncResult) - step 3 get
80
.Net的異步機制(APM核心:IAsyncResult) - step 3
.Net的異步機制(APM核心:IAsyncResult) - step 3
.Net的異步機制(APM核心:IAsyncResult) - step 3 {
81
.Net的異步機制(APM核心:IAsyncResult) - step 3 if (m_AsyncWaitHandle == null)
82
.Net的異步機制(APM核心:IAsyncResult) - step 3
.Net的異步機制(APM核心:IAsyncResult) - step 3
.Net的異步機制(APM核心:IAsyncResult) - step 3 {
83
.Net的異步機制(APM核心:IAsyncResult) - step 3 Boolean done = IsCompleted;
84
.Net的異步機制(APM核心:IAsyncResult) - step 3 ManualResetEvent mre = new ManualResetEvent(done);
85
.Net的異步機制(APM核心:IAsyncResult) - step 3 if (Interlocked.CompareExchange(ref m_AsyncWaitHandle,
86
.Net的異步機制(APM核心:IAsyncResult) - step 3 mre, null) != null)
87
.Net的異步機制(APM核心:IAsyncResult) - step 3
.Net的異步機制(APM核心:IAsyncResult) - step 3
.Net的異步機制(APM核心:IAsyncResult) - step 3 {
88
.Net的異步機制(APM核心:IAsyncResult) - step 3 // Another thread created this object's event; dispose
89
.Net的異步機制(APM核心:IAsyncResult) - step 3 // the event we just created
90
.Net的異步機制(APM核心:IAsyncResult) - step 3 mre.Close();
91
.Net的異步機制(APM核心:IAsyncResult) - step 3 }
92
.Net的異步機制(APM核心:IAsyncResult) - step 3 else
93
.Net的異步機制(APM核心:IAsyncResult) - step 3
.Net的異步機制(APM核心:IAsyncResult) - step 3
.Net的異步機制(APM核心:IAsyncResult) - step 3 {
94
.Net的異步機制(APM核心:IAsyncResult) - step 3 if (!done && IsCompleted)
95
.Net的異步機制(APM核心:IAsyncResult) - step 3
.Net的異步機制(APM核心:IAsyncResult) - step 3
.Net的異步機制(APM核心:IAsyncResult) - step 3 {
96
.Net的異步機制(APM核心:IAsyncResult) - step 3 // If the operation wasn't done when we created
97
.Net的異步機制(APM核心:IAsyncResult) - step 3 // the event but now it is done, set the event
98
.Net的異步機制(APM核心:IAsyncResult) - step 3 m_AsyncWaitHandle.Set();
99
.Net的異步機制(APM核心:IAsyncResult) - step 3 }
100
.Net的異步機制(APM核心:IAsyncResult) - step 3 }
101
.Net的異步機制(APM核心:IAsyncResult) - step 3 }
102
.Net的異步機制(APM核心:IAsyncResult) - step 3 return m_AsyncWaitHandle;
103
.Net的異步機制(APM核心:IAsyncResult) - step 3 }
104
.Net的異步機制(APM核心:IAsyncResult) - step 3 }
105
.Net的異步機制(APM核心:IAsyncResult) - step 3 106
.Net的異步機制(APM核心:IAsyncResult) - step 3 public Boolean IsCompleted
107
.Net的異步機制(APM核心:IAsyncResult) - step 3
.Net的異步機制(APM核心:IAsyncResult) - step 3
.Net的異步機制(APM核心:IAsyncResult) - step 3 {
108
.Net的異步機制(APM核心:IAsyncResult) - step 3 get
109
.Net的異步機制(APM核心:IAsyncResult) - step 3
.Net的異步機制(APM核心:IAsyncResult) - step 3
.Net的異步機制(APM核心:IAsyncResult) - step 3 {
110
.Net的異步機制(APM核心:IAsyncResult) - step 3 return Thread.VolatileRead(ref m_CompletedState) !=
111
.Net的異步機制(APM核心:IAsyncResult) - step 3 c_StatePending;
112
.Net的異步機制(APM核心:IAsyncResult) - step 3 }
113
.Net的異步機制(APM核心:IAsyncResult) - step 3 }
114
.Net的異步機制(APM核心:IAsyncResult) - step 3 #endregion
115
.Net的異步機制(APM核心:IAsyncResult) - step 3 }
2步,繼承AsyncResultNoResult對象,并且為他提供傳回值和泛型的通路
Code3.2
1
.Net的異步機制(APM核心:IAsyncResult) - step 3 internal class AsyncResult < TResult > : AsyncResultNoResult
2
.Net的異步機制(APM核心:IAsyncResult) - step 3
.Net的異步機制(APM核心:IAsyncResult) - step 3
.Net的異步機制(APM核心:IAsyncResult) - step 3 {
3
.Net的異步機制(APM核心:IAsyncResult) - step 3 // Field set when operation completes
4
.Net的異步機制(APM核心:IAsyncResult) - step 3 private TResult m_result = default(TResult);
5
.Net的異步機制(APM核心:IAsyncResult) - step 3 6
.Net的異步機制(APM核心:IAsyncResult) - step 3 public AsyncResult(AsyncCallback asyncCallback, Object state) :
7
.Net的異步機制(APM核心:IAsyncResult) - step 3
.Net的異步機制(APM核心:IAsyncResult) - step 3 base(asyncCallback, state)
.Net的異步機制(APM核心:IAsyncResult) - step 3 { }
8
.Net的異步機制(APM核心:IAsyncResult) - step 3 9
.Net的異步機制(APM核心:IAsyncResult) - step 3 public void SetAsCompleted(TResult result,
10
.Net的異步機制(APM核心:IAsyncResult) - step 3 Boolean completedSynchronously)
11
.Net的異步機制(APM核心:IAsyncResult) - step 3
.Net的異步機制(APM核心:IAsyncResult) - step 3
.Net的異步機制(APM核心:IAsyncResult) - step 3 {
12
.Net的異步機制(APM核心:IAsyncResult) - step 3 // Save the asynchronous operation's result
13
.Net的異步機制(APM核心:IAsyncResult) - step 3 m_result = result;
14
.Net的異步機制(APM核心:IAsyncResult) - step 3 15
.Net的異步機制(APM核心:IAsyncResult) - step 3 // Tell the base class that the operation completed
16
.Net的異步機制(APM核心:IAsyncResult) - step 3 // sucessfully (no exception)
17
.Net的異步機制(APM核心:IAsyncResult) - step 3 base.SetAsCompleted(null, completedSynchronously);
18
.Net的異步機制(APM核心:IAsyncResult) - step 3 }
19
.Net的異步機制(APM核心:IAsyncResult) - step 3 20
.Net的異步機制(APM核心:IAsyncResult) - step 3 new public TResult EndInvoke()
21
.Net的異步機制(APM核心:IAsyncResult) - step 3
.Net的異步機制(APM核心:IAsyncResult) - step 3
.Net的異步機制(APM核心:IAsyncResult) - step 3 {
22
.Net的異步機制(APM核心:IAsyncResult) - step 3 base.EndInvoke(); // Wait until operation has completed
23
.Net的異步機制(APM核心:IAsyncResult) - step 3 return m_result; // Return the result (if above didn't throw)
24
.Net的異步機制(APM核心:IAsyncResult) - step 3 }
25
.Net的異步機制(APM核心:IAsyncResult) - step 3 }
3步,模拟長時間的異步工作
Code3.3
1
.Net的異步機制(APM核心:IAsyncResult) - step 3 internal sealed class LongTask
2
.Net的異步機制(APM核心:IAsyncResult) - step 3
.Net的異步機制(APM核心:IAsyncResult) - step 3
.Net的異步機制(APM核心:IAsyncResult) - step 3 {
3
.Net的異步機制(APM核心:IAsyncResult) - step 3 private Int32 m_ms; // Milliseconds;
4
.Net的異步機制(APM核心:IAsyncResult) - step 3 5
.Net的異步機制(APM核心:IAsyncResult) - step 3 public LongTask(Int32 seconds)
6
.Net的異步機制(APM核心:IAsyncResult) - step 3
.Net的異步機制(APM核心:IAsyncResult) - step 3
.Net的異步機制(APM核心:IAsyncResult) - step 3 {
7
.Net的異步機制(APM核心:IAsyncResult) - step 3 m_ms = seconds * 1000;
8
.Net的異步機制(APM核心:IAsyncResult) - step 3 }
9
.Net的異步機制(APM核心:IAsyncResult) - step 3 10
.Net的異步機制(APM核心:IAsyncResult) - step 3 // Synchronous version of time-consuming method
11
.Net的異步機制(APM核心:IAsyncResult) - step 3 public DateTime DoTask()
12
.Net的異步機制(APM核心:IAsyncResult) - step 3
.Net的異步機制(APM核心:IAsyncResult) - step 3
.Net的異步機制(APM核心:IAsyncResult) - step 3 {
13
.Net的異步機制(APM核心:IAsyncResult) - step 3 Thread.Sleep(m_ms); // Simulate time-consuming task
14
.Net的異步機制(APM核心:IAsyncResult) - step 3 return DateTime.Now; // Indicate when task completed
15
.Net的異步機制(APM核心:IAsyncResult) - step 3 }
16
.Net的異步機制(APM核心:IAsyncResult) - step 3 17
.Net的異步機制(APM核心:IAsyncResult) - step 3 // Asynchronous version of time-consuming method (Begin part)
18
.Net的異步機制(APM核心:IAsyncResult) - step 3 public IAsyncResult BeginDoTask(AsyncCallback callback, Object state)
19
.Net的異步機制(APM核心:IAsyncResult) - step 3
.Net的異步機制(APM核心:IAsyncResult) - step 3
.Net的異步機制(APM核心:IAsyncResult) - step 3 {
20
.Net的異步機制(APM核心:IAsyncResult) - step 3 // Create IAsyncResult object identifying the
21
.Net的異步機制(APM核心:IAsyncResult) - step 3 // asynchronous operation
22
.Net的異步機制(APM核心:IAsyncResult) - step 3 AsyncResult<DateTime> ar = new AsyncResult<DateTime>(
23
.Net的異步機制(APM核心:IAsyncResult) - step 3 callback, state);
24
.Net的異步機制(APM核心:IAsyncResult) - step 3 25
.Net的異步機制(APM核心:IAsyncResult) - step 3 // Use a thread pool thread to perform the operation
26
.Net的異步機制(APM核心:IAsyncResult) - step 3 ThreadPool.QueueUserWorkItem(DoTaskHelper, ar);
27
.Net的異步機制(APM核心:IAsyncResult) - step 3 28
.Net的異步機制(APM核心:IAsyncResult) - step 3 return ar; // Return the IAsyncResult to the caller
29
.Net的異步機制(APM核心:IAsyncResult) - step 3 }
30
.Net的異步機制(APM核心:IAsyncResult) - step 3 31
.Net的異步機制(APM核心:IAsyncResult) - step 3 // Asynchronous version of time-consuming method (End part)
32
.Net的異步機制(APM核心:IAsyncResult) - step 3 public DateTime EndDoTask(IAsyncResult asyncResult)
33
.Net的異步機制(APM核心:IAsyncResult) - step 3
.Net的異步機制(APM核心:IAsyncResult) - step 3
.Net的異步機制(APM核心:IAsyncResult) - step 3 {
34
.Net的異步機制(APM核心:IAsyncResult) - step 3 // We know that the IAsyncResult is really an
35
.Net的異步機制(APM核心:IAsyncResult) - step 3 // AsyncResult<DateTime> object
36
.Net的異步機制(APM核心:IAsyncResult) - step 3 AsyncResult<DateTime> ar = (AsyncResult<DateTime>)asyncResult;
37
.Net的異步機制(APM核心:IAsyncResult) - step 3 38
.Net的異步機制(APM核心:IAsyncResult) - step 3 // Wait for operation to complete, then return result or
39
.Net的異步機制(APM核心:IAsyncResult) - step 3 // throw exception
40
.Net的異步機制(APM核心:IAsyncResult) - step 3 return ar.EndInvoke();
41
.Net的異步機制(APM核心:IAsyncResult) - step 3 }
42
.Net的異步機制(APM核心:IAsyncResult) - step 3 43
.Net的異步機制(APM核心:IAsyncResult) - step 3 // Asynchronous version of time-consuming method (private part
44
.Net的異步機制(APM核心:IAsyncResult) - step 3 // to set completion result/exception)
45
.Net的異步機制(APM核心:IAsyncResult) - step 3 private void DoTaskHelper(Object asyncResult)
46
.Net的異步機制(APM核心:IAsyncResult) - step 3
.Net的異步機制(APM核心:IAsyncResult) - step 3
.Net的異步機制(APM核心:IAsyncResult) - step 3 {
47
.Net的異步機制(APM核心:IAsyncResult) - step 3 // We know that it's really an AsyncResult<DateTime> object
48
.Net的異步機制(APM核心:IAsyncResult) - step 3 AsyncResult<DateTime> ar = (AsyncResult<DateTime>)asyncResult;
49
.Net的異步機制(APM核心:IAsyncResult) - step 3 try
50
.Net的異步機制(APM核心:IAsyncResult) - step 3
.Net的異步機制(APM核心:IAsyncResult) - step 3
.Net的異步機制(APM核心:IAsyncResult) - step 3 {
51
.Net的異步機制(APM核心:IAsyncResult) - step 3 // Perform the operation; if sucessful set the result
52
.Net的異步機制(APM核心:IAsyncResult) - step 3 DateTime dt = DoTask();
53
.Net的異步機制(APM核心:IAsyncResult) - step 3 ar.SetAsCompleted(dt, false);
54
.Net的異步機制(APM核心:IAsyncResult) - step 3 }
55
.Net的異步機制(APM核心:IAsyncResult) - step 3 catch (Exception e)
56
.Net的異步機制(APM核心:IAsyncResult) - step 3
.Net的異步機制(APM核心:IAsyncResult) - step 3
.Net的異步機制(APM核心:IAsyncResult) - step 3 {
57
.Net的異步機制(APM核心:IAsyncResult) - step 3 // If operation fails, set the exception
58
.Net的異步機制(APM核心:IAsyncResult) - step 3 ar.SetAsCompleted(e, false);
59
.Net的異步機制(APM核心:IAsyncResult) - step 3 }
60
.Net的異步機制(APM核心:IAsyncResult) - step 3 }
61
.Net的異步機制(APM核心:IAsyncResult) - step 3 }
來自Jeffrey Richter大師更多更詳細的異步操作方法, 請檢視http://www.wintellect.com/PowerThreading.aspx,對于一些朋友可能看不懂Code3.1-3.3代碼(其實沒什麼所謂的),因為涉及到過多的線程知識,這裡出于讓你獲得更多的更深層次的(異步)認識為目的,才提供上面代碼,在以後的文章會再次探讨.
下一篇章中,我們來看看微軟提供有異步調用的類是如何調用的,并從中我會給出些真實應用環境中的一些小技巧,讓你編寫的代碼更健壯更完善.
以上有word 文檔直接粘貼,排版可能不太看,你可以通過下面來下載下傳相應的代碼/文檔
1,文檔
2,代碼(VS2008開發,.Net Framework 2.0(C Sharp)編寫)