在主線程中異步調用的方法不在主線程中執行,而是在另外一個輔助線程中與主線程代碼並行執行。給出一段示例代碼:異步
當咱們調用UploadPictureAsync方法時,圖片還沒有上傳完成,咱們就能夠在控制檯輸出提示信息:「圖片開始上傳」。async
/// <summary> /// 異步上傳圖片 /// </summary> /// <param name="fileLocalPath"></param> public void UploadPictureAsync(string id, string fileLocalPath) { DelegateMgr.UploadFileHandler del = new DelegateMgr.UploadFileHandler(UploadFile); del.BeginInvoke(id, fileLocalPath, delegate(IAsyncResult ar) { try { string fileUri = del.EndInvoke(ar); FileUploadEventArgs args = new FileUploadEventArgs(id, fileUri); if (PictureUploadCompleted != null) { PictureUploadCompleted(args); } } catch (Exception ex) { LogUtility.LogTableMessage("圖片上傳異常," + ex); } }, null);spa
Console.WriteLine("圖片開始上傳" ); } private string UploadFile(string id, string filePath) { string fileUri = string.Empty; try { WebClient wc = new WebClient(); string targetPath = "http://172.16.50.179:8090/FileUpload/ImageUpLoad.do"; byte[] bytes = wc.UploadFile(targetPath, "POST", filePath); fileUri = Encoding.Default.GetString(bytes);線程
Console.WriteLine("圖片完成上傳" ); } catch (Exception exception) { LogUtility.LogTableMessage("上傳圖片異常," + exception); } return fileUri; } public event Action<FileUploadEventArgs> PictureUploadCompleted;code
當咱們定義一個委託時,編譯器會爲委託生成一個類。好比咱們定義以下委託:對象
public delegate int DemoDelegate(int a, int b);
編譯器會生成以下格式的類:blog
public sealed class DemoDelegate : MulticastDelegate { public DemoDelegate(object @object, IntPtr method) { // } public virtual int Invoke(int a, int b) { //方法體爲空 } public virtual IAsyncResult BeginInvoke(int a, int b, AsyncCallback callback, object asyncState) { //方法體爲空 } public virtual int EndInvoke(IAsyncResult ar) { //方法體爲空 } }
class Program { static void Main(string[] args) { DemoDelegate del = new DemoDelegate(Add); //同步調用 Console.WriteLine("1 + 2 = " + del(1, 2)); } static int Add(int a, int b) { return a + b; } }
上面這種同步調用方式,實際上調用的是委託類的 Invoke 方法。接口
基於委託的異步調用,其實是經過 BeginInvoke 和 EndInvoke 兩個方法來實現的。圖片
咱們先來分析一下BeginInvoke方法get
public IAsyncResult BeginInvoke(
<輸入和輸出變量>,
AsyncCallback callback, object asyncState
)
<輸入和輸出變量>,表示委託聲明中,參數有ref或者out修飾的。
callback,異步調用結束時自動回調的方法
asyncState,用於向callback方法提供參數信息,好比回調方法須要一些參數,asyncState 就能夠用於填充這些參數。
對BeginInvoke方法的返回類型 IAsyncResult接口的說明
[ComVisible(true)] public interface IAsyncResult { object AsyncState { get; } WaitHandle AsyncWaitHandle { get; } bool CompletedSynchronously { get; } bool IsCompleted { get; } }
AsyncState,直接存儲BeginInvoke方法中傳入的 asyncState 參數值
AsyncWaitHandle,當異步操做完成時,該句柄處於 signaled 狀態。
CompletedSynchronously,表示BeginInvoke是否同步調用完成。
IsCompleted,能夠經過循環查詢該屬性判斷異步操做是否完成。
接下來咱們分析一下 EndInvoke 方法
public <方法返回值類型> EndInvoke(
<聲明爲ref或out的參數>,
IAsyncResult result)
調用 BeginInvoke方法會返回一個類型爲 IAsyncResult 的對象,該對象會做爲 EndInvoke方法的參數,這樣EndInvoke方法不斷輪詢異步執行結果,發現異步調用完成時,會將異步調用結果做爲返回值,若是異步調用方法有 ref 或者 out參數,也會負責填充這些參數。
調用者線程 輔助線程
|
①BeginInvoke ------------------------>
| ②異步調用方法執行
③EndInvoke <-------------------------