首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

並發事件:使用 AsyncEnumerator 簡化 APM (3) — HtmlToFile 迭代器實戰:非同步下載網頁並分塊寫入檔案

     編輯:關於C語言

Figure 2:HtmlToFile 迭代器


private static IEnumerator<Int32> HtmlToFile(AsyncEnumerator ae, String url, String file) {
    WebRequest webRequest = WebRequest.Create(url);
    webRequest.BeginGetResponse(ae.End(), null);
    yield return 1;

    WebResponse webResponse;
    try {
        webResponse = webRequest.EndGetResponse(ae.DequeueAsyncResult());
    } catch (WebException e) {
        Console.WriteLine("Failed to contact server: {0}", e.Message);
        yield break;
    }

    using (webResponse) {
        Stream webResponseStream = webResponse.GetResponseStream();
        Byte[] data = new Byte[1024];
        using (FileStream fs = new FileStream(file, FileMode.Create, FileAccess.Write, FileShare.None, data.Length, FileOptions.Asynchronous)) {
            fs.SetLength(webResponse.ContentLength);
            while (true) {
                webResponseStream.BeginRead(data, 0, data.Length, ae.End(), null);
                yield return 1;
                Int32 bytesRead = webResponseStream.EndRead(ae.DequeueAsyncResult());
                if (bytesRead == 0) break;
                fs.BeginWrite(data, 0, bytesRead, ae.End(), null);
                yield return 1;
                fs.EndWrite(ae.DequeueAsyncResult());
            }
        }
    }
}

關鍵點

  • ae.End() 回傳 AsyncCallback,完成時將 IAsyncResult 入收件箱。
  • ae.DequeueAsyncResult() 以 FIFO 取出結果供 EndXxx 使用。
  • yield return 1 暫停等待單一作業;迴圈中連續 Read → yield → Write → yield 實現流水線非同步。
  • yield break 於例外時終止迭代器。

呼叫方式


AsyncEnumerator ae = new AsyncEnumerator();
ae.Execute(HtmlToFile(ae, "https://www.Wintellect.com/", "LocalFile.Html"));

迭代器各段代碼理論上可由不同執行緒池執行緒執行,**不得依賴執行緒區域儲存/UI 執行緒/優先權等執行緒特定狀態**。

非阻塞執行迭代器

目前 Execute 會阻塞呼叫執行緒直到迭代器結束,適合測試。WinForms/WPF 需從 UI 執行緒啟動且不阻塞,下一節將介紹非阻塞執行模式。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved