在前面一篇博文記錄了C#中的APM非同步編程的知識,今天再來分享一下EAP(基於事件的非同步編程模式)非同步編程的知識。後面會繼續奉上TPL任務並行庫的知識,喜歡的朋友請持續關註哦。 ...
在前面一篇博文記錄了C# APM非同步編程的知識,今天再來分享一下EAP(基於事件的非同步編程模式)非同步編程的知識。後面會繼續奉上TPL任務並行庫的知識,喜歡的朋友請持續關註哦。
EAP非同步編程算是C#對APM的一種補充,讓非同步編程擁有了一系列狀態事件。如果你看過本系列的前一篇文章《C# 非同步編程1 APM 非同步程式開發》,並假設你是微軟C#語言開發組的一員,現在讓你來設計基於事件的非同步編程模式。那你是會利用之前的APM進行改造?還是進行再次創造呢?所以當你對相關dll進行反編譯,會驚喜的發現EAP實際上是對APM增加了事件event後的封裝。因此這篇博文的篇幅不會很長,我們只介紹EAP模式的基本信息和編程實現。對於事件 event 我後續增加博文闡述其功能及用法。
EAP 基於事件的非同步編程模式
當我們使用EAP模式進行非同步編程時,需要滿足以下2個條件:
1、要進行非同步的方法其方法名應該以XXXAsync結尾
2、要有一個名為XXXCompleted的事件監聽非同步方法的完成
3、可增加一個CancelAsync方法用於取消正在執行的非同步方法(可選)
示例代碼:
/// <summary> /// EAP是對APM的封裝 /// </summary> public class Worker { public enum WorkerStatus { Cancel = 0,Running=1, Completed=2 } public class WorkerEventArgs :EventArgs { public WorkerStatus Status { get; set; } public string Message { get; set; } } public Worker() { } public event EventHandler<WorkerEventArgs> OnWorkCompleted; IAsyncResult asyncResult = null; Thread thread = null; public void WorkAsync() { Worker _this = this; Action action = () => { thread = Thread.CurrentThread; Thread.Sleep(10000); Console.WriteLine(string.Format("線程:{0},Work Over.", Thread.CurrentThread.ManagedThreadId)); }; asyncResult = action.BeginInvoke((result) => { WorkerEventArgs e = null; try { action.EndInvoke(asyncResult); } catch (ThreadAbortException ex) { e = new WorkerEventArgs() { Status = WorkerStatus.Cancel, Message = "非同步操作被取消" }; } if (null != _this.OnWorkCompleted) { _this.OnWorkCompleted.Invoke(this, e); } }, this); } public void CancelAsync() { if (null != thread) thread.Abort(); } }
調用程式使用WinForm來進行,示例代碼如下(僅為演示用):
Worker worker; private void Btn_Start_Click(object sender, EventArgs e) { worker = new Worker(); worker.OnWorkCompleted += WorkOver; worker.WorkAsync(); Console.WriteLine(string.Format("線程:{0}", Thread.CurrentThread.ManagedThreadId)); } private void Btn_Cancel_Click(object sender, EventArgs e) { worker.CancelAsync(); } private void WorkOver(object sender, Worker.WorkerEventArgs e) { if (null != e) { if (Worker.WorkerStatus.Cancel == e.Status) { MessageBox.Show(e.Message); } } else { Console.WriteLine(string.Format("線程:{0},委托回調完成.", Thread.CurrentThread.ManagedThreadId)); } }
效果展示:
註意事項(重要):
1、APM非同步編程時,因非同步代碼執行在單獨的線程中,非同步代碼中出現的異常應該在調用EndXXX時捕獲。
2、EAP非同步編程時,因上述同樣原因,代碼中的異常信息會被傳遞到Completed事件的EventArgs參數中。
EAP(基於事件的非同步編程模式)核心內容並不多,並且如網路、IO等耗時類 Ms 已添加了EAP相關非同步功能,我們直接拿來用就好。尤其是後續TPL並行任務的加入,用戶自定義EAP非同步功能的機會更是了了,但EAP中相關的知識點如線程、委托、事件等仍然是重要的.......................
TPL任務並行庫正在快馬加鞭趕來中...............