在閱讀下面知識前,我已經認為你已經具有c#的基礎,包括簡單的委托知識; 代碼使用VS2008開發,但是會在.Net Framework 2.0(C Sharp)編寫
什麼是.Net異步機制呢?
在解釋這個話題前,我們先看看同步的程序,就是我們常用的Hello World 程序.
Code 1:
1 class Program 2 { 3 static void Main(string[] args) 4 { 5 // 查看當前的線程ID, 是否線程池裡面的線程 6 Console.WriteLine("1,Thread ID:#{0},Is PoolThread?{1}", Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsThreadPoolThread); 7 8 AsyncTest test = new AsyncTest(); 9 string val = test.Hello("Andy Huang"); 10 11 Console.WriteLine(val); 12 Console.ReadLine(); // 讓黑屏等待,不會直接關閉.. 13 } 14 } 15 16 public class AsyncTest 17 { 18 public string Hello(string name) 19 { 20 // 查看當前的線程ID, 是否線程池裡面的線程 21 Console.WriteLine("2,Thread ID:#{0},Is PoolThread?{1}", Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsThreadPoolThread); 22 return "Hello:" + name; 23 } 24 }
圖1
我們可以從圖1看出,我們平常寫的Hello 程序是同一個線程的,而且不是線程池理的線程程序.
按照上面的程序稍做改動, 那麼開始我們第一個異步的Hello World 程序.
使用.Net 的委托機制來為我們的程序提供異步操作行為.
1步, 為我們的AsyncTest(Hello方法) 聲明一個委托
public delegate string AsyncEventHandler(string name);
2步,使用委托提供的BeginInvoke, EndInvoke 方法(具體使用下一篇文章詳細介紹)來提供異步的調用.
string val = test.Hello("Andy Huang");
修改為
AsyncEventHandler async = test.Hello; IAsyncResult result = async.BeginInvoke("Andy Huang", null, null); string val = async.EndInvoke(result);
下面是完整的代碼.
Code 2:
1 class Program 2 { 3 static void Main(string[] args) 4 { 5 // 查看當前的線程ID, 是否線程池裡面的線程 6 Console.WriteLine("1,Thread ID:#{0},Is PoolThread?{1}", Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsThreadPoolThread); 7 8 AsyncTest test = new AsyncTest(); 9 //把Hello 方法分配給委托對象 10 AsyncEventHandler async = test.Hello; //注釋1,建議用=,不用+= 11 12 //發起一個異步調用的方法,賦值"Andy Huang", 返回IAsyncResult 對象 13 IAsyncResult result = async.BeginInvoke("Andy Huang", null, null); 14 15 //這裡會阻礙線程,直到方法執行完畢 16 string val = async.EndInvoke(result); 17 18 Console.WriteLine(val); 19 Console.ReadLine(); // 讓黑屏等待,不會直接關閉.. 20 } 21 } 22 23 //我們使用委托來提供.Net的異步機制 24 public delegate string AsyncEventHandler(string name); 25 public class AsyncTest 26 { 27 public string Hello(string name) 28 { 29 // 查看當前的線程ID, 是否線程池裡面的線程 30 Console.WriteLine("2,Thread ID:#{0},Is PoolThread?{1}", Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsThreadPoolThread); 31 return "Hello:" + name; 32 } 33 }
注釋1: 用=操作符在於分配委托對象時候不需要初始化;並且異步調用時候只能有一個目標方法.
圖2
對比圖1 和圖2, ,可以看出(2,Thread ID:#10,Is PoolThread?True),在使用異步機制的時候,其實就是開啟一個新的線程來執行我們的方法,並且這個線程來自 線程堆. 到這裡,我們就很好的解釋了”什麼是.Net異步機制?”
說到這裡,結束了嗎? 可能大家會想其實使用異步就是多了個委托( public delegate string AsyncEventHandler(string name);) 那麼到底為我們做了些什麼呢?
通過反編譯(微軟提供的IL Disassembler)我們看到
圖3
編譯器為我們生成了下面類定義(其實委托就是一個類)
Code 3
public sealed class AsyncEventHandler : MulticastDelegate { public AsyncEventHandler(object @object, IntPtr method) {....} public virtual IAsyncResult BeginInvoke(string name, AsyncCallback callback, object @object) {...} public virtual string EndInvoke(IAsyncResult result) {...} public virtual string Invoke(string name) {...} }
繼承於MulticastDelegate, 提供了BeginInvoke / EndInvoke / Invoke.
Invoke 是我們Code 1 同步調用的方法,當然我們也可以直接使用Invoke來同步調用.
BeginInvoke / EndInvoke 是Code 2中使用的異步調用的方法,下篇文章我會詳細介紹
什麼時候使用.Net異步機制呢?
異步操作通常用於執行完成時間可能較長的任務,如打開大文件、連接遠程計算機或查詢數據庫。異步操作在主應用程序線程以外的線程中執行。應用程序調用方法異步執行某個操作時,應用程序仍然可以繼續執行當前的程序。
.NET Framework 的許多方面都支持異步編程功能,這些方面包括:
·文件(File) IO、流(Stream) IO、套接字(Socket) IO。
·網絡。
·遠程處理信道(HTTP、TCP)和代理。
·使用 ASP.NET 創建的 XML Web services。
·ASP.NET Web 窗體。
·使用 MessageQueue 類的消息隊列。
本文配套源碼