委託的Invoke方法用來進行同步調用。同步調用也能夠叫阻塞調用,它將阻塞當前線程,而後執行調用,調用完畢後再繼續向下進行。
編程
異步調用不阻塞線程,而是把調用塞到線程池中,程序主線程或UI線程能夠繼續執行。個人理解是雖然表面上沒有新開啓線程,但實際上異步調用時CLR自動爲你開啓了一個新線程。委託的異步調用經過Beginxxx和Endxxx來實現。這種方式稱爲APM 異步編程模型。app
Beginxxx : 開始一個異步的請求,調用線程池中一個線程來執行
返回IAsyncResult 對象(異步的核心). IAsyncResult 簡單的說,他存儲異步操做的狀態信息的一個接口,也能夠用他來結束當前異步。
注意: Beginxxx和Endxxx必須成對調用.即便不須要返回值,但Endxxx仍是必須調用,不然可能會形成內存泄漏。
異步
(1)定義委託:
public virtual IAsyncResult BeginInvoke(int abc, AsyncCallBack callback, object asyncState) 和 public virtual string EndInvoke(IAsyncResult asyncResult)async
MyDelegate m_MyDelegate = fun異步編程
fun與m_MyDelegate 具備相同簽名的方法函數
(3)調用:}spa
BeginInvoke方法前部分的參數是用來給調用它的委託對象所代理的那個方法傳遞參數即傳給fun,最後兩個參數爲可選,第一個是用來聲明回調函數的方法名,第二個參數是 "傳遞額外的參數",在這裏是傳給onComplete。經過BeginInvoke方法的最後一個參數能夠在調用方和回調函數之間傳遞狀態,由於他自己是Object對象,咱們能夠傳遞任何對象。
線程
回調方法的參數永遠都是IAsyncResult ,沒辦法直接給回調方法傳遞本身想要的參數,因此只能經過asyncState來間接的傳遞給回調方法。代理
在回調函數中如何取得這個參數呢?AsyncResult 類封裝的AsyncState屬性保存了BeginInvoke 的最後一個參數,咱們能夠經過它獲得。關於這一部分的知識能夠看我另外一篇博客AsyncResult 類的使用。code
EndInvoke方法是在回調方法裏被調用來獲取執行結果。
注意EndInvoke和回調函數接收的參數都是BeginInvoke的返回值m_AsyncResult ,而EndInvoke的返回值正是委託方法的返回類型(在這裏就是string)。
下面MSDN的代碼示例演示如何使用 Dns 類中的異步方法來檢索用戶指定的計算機的域名系統 (DNS) 信息。 此示例建立一個引用 ProcessDnsInformation 方法的 AsyncCallback 委託。 對各個針對 DNS 信息發出的異步請求,將分別調用一次此方法。
/* The following example demonstrates using asynchronous methods to get Domain Name System information for the specified host computers. This example uses a delegate to obtain the results of each asynchronous operation. */ using System; using System.Net; using System.Net.Sockets; using System.Threading; using System.Collections.Specialized; using System.Collections; namespace Examples.AdvancedProgramming.AsynchronousOperations { public class UseDelegateForAsyncCallback { static int requestCounter; static ArrayList hostData = new ArrayList(); static StringCollection hostNames = new StringCollection(); static void UpdateUserInterface() { // Print a message to indicate that the application // is still working on the remaining requests. Console.WriteLine("{0} requests remaining.", requestCounter); } public static void Main() { // Create the delegate that will process the results of the // asynchronous request. AsyncCallback callBack = new AsyncCallback(ProcessDnsInformation);//定義回調函數 string host; do { Console.Write(" Enter the name of a host computer or <enter> to finish: "); host = Console.ReadLine(); if (host.Length > 0) { // Increment the request counter in a thread safe manner. Interlocked.Increment(ref requestCounter); // Start the asynchronous request for DNS information. Dns.BeginGetHostEntry(host, callBack, host); } } while (host.Length > 0); // The user has entered all of the host names for lookup. // Now wait until the threads complete. while (requestCounter > 0) { UpdateUserInterface(); } // Display the results. for (int i = 0; i< hostNames.Count; i++) { object data = hostData [i]; string message = data as string; // A SocketException was thrown. if (message != null) { Console.WriteLine("Request for {0} returned message: {1}", hostNames[i], message); continue; } // Get the results. IPHostEntry h = (IPHostEntry) data; string[] aliases = h.Aliases; IPAddress[] addresses = h.AddressList; if (aliases.Length > 0) { Console.WriteLine("Aliases for {0}", hostNames[i]); for (int j = 0; j < aliases.Length; j++) { Console.WriteLine("{0}", aliases[j]); } } if (addresses.Length > 0) { Console.WriteLine("Addresses for {0}", hostNames[i]); for (int k = 0; k < addresses.Length; k++) { Console.WriteLine("{0}",addresses[k].ToString()); } } } } // The following method is called when each asynchronous operation completes. static void ProcessDnsInformation(IAsyncResult result) { string hostName = (string) result.AsyncState;//傳值 hostNames.Add(hostName); try { // Get the results. IPHostEntry host = Dns.EndGetHostEntry(result);//取結果 hostData.Add(host); } // Store the exception message. catch (SocketException e) { hostData.Add(e.Message); } finally { // Decrement the request counter in a thread-safe manner. Interlocked.Decrement(ref requestCounter); } } } }