.Net中的非同步編程模式 (APM) (二)

來源:互聯網
上載者:User
文章目錄
  • 為什麼要自己實現APM
  • PowerThreading類庫中的AsyncResult和AsyncResult<T>

Note: 本篇主要內容來自Jeffery Richard的Implementing the CLR Asynchronous Programming Model,看過的同學可以略過。

在前一篇中介紹了使用APM開發多線程程式的有點,同時關於如何使用APM方式的文章也很多了。所以,這篇主要想看看如何使用Jeffery Richard的Power Threading類庫,來開發一個支援APM的類。

為什麼要自己實現APM

前一篇中,提到了受計算約束(Computing-Bound)與受I/O約束(I/O-Bound)的區別。如果我們是一個受計算約束類型的任務,完全可以將這個方法變成委託(Delegate)的形式,然後通過BeginInvoke/EndInvoke來實現APM;另外,FCL本身也封裝了大量對I/O非同步作業的類,如FileStream,NetworkStream等,那我們為什麼還要自己實現APM呢。Jeffery Richard列舉了4個原因:

  1. 儘管FCL提供很多與裝置通訊的非同步類,但仍有部分未提供,如並口;或者FCL提供的功能不夠
  2. 對現有的I/O類庫添加功能,如我們在WebHttpRequest可以開發一個HTTP的過濾類等
  3. 實現受計算約束的APM
  4. 對不支援非同步模式裝置提供非同步訪問方式
PowerThreading類庫中的AsyncResult和AsyncResult<T>

APM的核心就是IAsyncResult介面。當調用類非同步方式BeginXxx時,返回IAsyncResult的對象。為了返回滿足這個介面的對象,我們的類需要維護的一個 是否完成的狀態IsCompleted;一個ManuelResetEvent對象及一個委託保持回呼函數。這些雖然比較簡單,但很麻煩。使用PowerThreading類庫中AsyncResult和AsyncResult<T>,我們可以非常容易的實現支援APM的類。

AsyncResult用於沒有傳回值,而AsyncResult<T>用於傳回型別為T的任務。下面的例子中,我們看看如何使用AsyncResult<T>。

首先,我們準備實現一個能夠過濾Stream對象的類,類定義如下:

 1 class StreamFilter
 2 {
 3    private Stream                   m_stream;
 4    public StreamFilter(Stream stream)
 5    {
 6    }
 7 
 8    public IAsyncResult BeginParse(
 9             AsyncCallback callback, Object state)
10    {
11    }
12 
13    public Stream Parse()
14    {
15    }
16 
17    public Stream EndParse(IAsyncResult asyncResult)
18    {
19    }
20 }

Parse()是同步提供者,執行主要的任務,而BeginParse()和EndParse()是對應的非同步介面。下面是使用AsyncResult<T>後的代碼

 1 class StreamFilter
 2 {
 3    private Stream                   m_stream;
 4    public StreamFilter(Stream stream)
 5    {
 6       m_stream = stream;
 7    }
 8 
 9    public IAsyncResult BeginParse(
10             AsyncCallback callback, Object state)
11    {
12       //建立一個IAsyncResult對象來標誌非同步作業
13       AsyncResult<Stream> ar = 
14             new AsyncResult<Stream>(callback, state);
15 
16       // 調用輔助函數,並傳遞AsycnResult對象
17       // 如果使用Anonymouse Method更簡潔
18       ThreadPool.QueueUserWorkItem(ParseHelper,ar);
19 
20       return ar; // 返回IAsyncResult
21    }
22 
23    private void ParseHelper(Object asyncResult)
24    {
25       var ar = (AsyncResult<Stream>)asyncResult;
26       try
27       {
28          // 執行真正的任務
29          Stream result = Parse();
30 
31          // 更新AsycnResult狀態
32          ar.SetAsCompleted(result, false);
33       } catch (Exception e)
34       {
35          // 儲存Exception對象
36          ar.SetAsCompleted(e, false);
37       }
38    }
39 
40    public Stream Parse()
41    {
42       // 分析m_stream,並返回過濾後的stream對象
43       Stream filterStream = null;
44       return filterStream;
45    }
46 
47    public Stream EndParse(IAsyncResult asyncResult)
48    {
49       var ar = (AsyncResult<Stream>)asyncResult;
50       // 等待任務完成
51       return ar.EndInvoke();
52    }
53 }

 

比較重要的是ParseHelper函數,這個函數在新的線程中執行,通過ar.SetAsCompleted來更新狀態。 如果結合匿名方法或者Limbda運算式,代碼可以變得更加的緊湊。

 

參考:

Implementing the CLR Asynchronous Programming Model by Jeffery Richard

Power Threading類庫

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.