程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> 並發事件:使用AsyncEnumerator簡化APM(1)

並發事件:使用AsyncEnumerator簡化APM(1)

編輯:關於C語言

目錄

使用 AsyncEnumerator 類

AsyncEnumerator 的體系結構

使用 Wait 和 Inbox 計數器

線程安全變形

了解更多信息

在上期專欄 (並發事件: 通過 C# 簡化 APM) 中,,我講述了一些有關如何使用新的 C# 語言功能( 匿名方法、lambda 表達式和迭代器)簡化異步編程的理念。在專欄最後,我說明了如何借助 C# 迭代器 使用同步編程模型完成異步編程。圖 1 顯示了示例迭代器。不過,僅使用常規的 C# foreach 語句是無 法執行迭代器的代碼的,因為此代碼始終由調用 foreach 的線程執行,並且是連續執行,不會暫停來完 成異步 I/O 操作。

在本期專欄中,我將介紹我的 AsyncEnumerator 類,它可以智能地驅動迭代器,使不同的線程池線程 能夠在不同的時間執行代碼,我可以確保迭代器只有在完成異步 I/O 操作後才會執行下一次迭代。此外 ,我還會介紹 AsyncEnumerator 類的體系結構及其工作原理。

使用 AsyncEnumerator 類

下面是 AsyncEnumerator 類的定義:

public class AsyncEnumerator {
  // Methods called by code outside of the iterator
  public AsyncEnumerator();
  public void Execute(IEnumerator<Int32> enumerator);
  // Methods called by code inside the iterator
  public AsyncCallback End();
  public IAsyncResult DequeueAsyncResult();
}

AsyncEnumerator 類的用法相當簡單。首先,我們來介紹如何實現您的迭代器成員,然後再介紹如何 調用。

將迭代器成員定義為可以接受所需的任何參數,並添加一個附加參數,該參數是對 AsyncEnumerator 對象的引用。返回 Int32 集合時您的迭代器成員必須設為原型;換句話說,它的返回類型必須是 IEnumerator<Int32>。

然後,在迭代器成員內部,通過調用相應的 BeginXxx 方法啟動每個異步操作。您知道,如果調用 BeginXxx 方法,則必須將完成異步操作時應調用的方法的名稱傳遞給它。

您可以調用 AsyncEnumerator 對象的 End 方法,而不需要定義自己的方法。End 方法會返回一個 AsyncCallback 代理,此代理標識在 AsyncEnumerator 類中定義的私有方法。因此,每個異步操作完成 時,AsyncEnumerator 對象中的代碼都會得到通知。然後,此代碼會將已完成的操作的 IAsyncResult 對 象放到 List<IAsyncResult> 對象(我稱它為 inbox,即收件箱)中。

在您的代碼中,在調用 BeginXxx 方法之後,放置一個 yield return 語句,用於返回排隊等候的異 步操作數。在圖 1 中,因為我只調用了一個 BeginXxx 方法 (BeginRead),所以 yield return 語句返 回值 1。yIEld return 語句將暫停您的迭代器方法,並停止執行其中的代碼。

圖 1 C# 迭代器

private static IEnumerator<Int32> ApmPatternWithIterator(
  AsyncEnumerator ae, String pathname) {
  using (FileStream fs = new FileStream(pathname, FileMode.Open,
    FileAccess.Read, FileShare.Read, 8192, FileOptions.Asynchronous)) {
    Byte[] data = new Byte[fs.Length];
    fs.BeginRead(data, 0, data.Length, ae.End(), null);
    yIEld return 1;
    Int32 bytesRead = fs.EndRead(ae.DequeueAsyncResult());
    ProcessData(data);
  }
}

稍後,我會提供一些讓 yield return 語句返回非 1 值的其他示例,但對於許多應用程序而言,還是 返回 1 比較合適。在 yield return 語句中指定的數字用於告知 AsyncEnumerator 對象需要完成多少個 異步操作才能恢復迭代器的執行。因此,當迭代器暫停時,您啟動的所有異步操作都會繼續完成。完成每 個異步操作後,AsyncEnumerator 的收件箱中都會增加一個條目。當收件箱中的項目數等於您在 yIEld return 語句中指定的數字時,AsyncEnumerator 對象將恢復迭代器的執行,並允許繼續執行其代碼。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved