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

Windows 8 Store Apps 非同步程式設計演進:從 IAsyncResult 到 async/await 與 Task 互轉

     編輯:關於.NET

前言

非同步程式設計模型經歷了三代演進:APM(IAsyncResult)、EAP(事件基礎模式)與 TAP(async/await + Task)。Windows 8 Store Apps 採用 WinRT 非同步模式(EAP 變體),但完全相容 Task 體系。本文對比經典與現代模式,並詳細說明 IAsyncInfo 與 Task 雙向轉換技術。

第一代:APM(Asynchronous Programming Model)

IAsyncResult 模式 以 BeginXxx/EndXxx 配對方法為特徵,需手動管理回呼與狀態物件:

public class ClassicAsync {
    private delegate string HelloDelegate(string name);
    private readonly HelloDelegate _hello = name => {
        Thread.Sleep(3000);
        return "hello: " + name;
    };

    public IAsyncResult BeginRun(string name, AsyncCallback callback, object state) {
        return _hello.BeginInvoke(name, callback, state);
    }

    public string EndRun(IAsyncResult ar) {
        return _hello.EndInvoke(ar);
    }
}

// 使用方式
var classic = new ClassicAsync();
IAsyncResult ar = classic.BeginRun("webabcd", ar => {
    var result = classic.EndRun(ar);
    // 需手動切回 UI 線程
    Dispatcher.RunAsync(..., () => lbl.Text = result);
}, null);

缺點: 程式碼碎片化、例外處理分散、巢狀回呼地獄、無標準取消機制。

第二代:EAP(Event-based Asynchronous Pattern)

以 XxxAsync 方法 + XxxCompleted 事件為特徵,BackgroundWorker、WebClient 為典型代表。WinRT 非同步介面(IAsyncAction 等)可視為 EAP 的標準化演進。

第三代:TAP(Task-based Asynchronous Pattern)

async/await 配合 Task/Task<T> 是現代 .NET 非同步開發的標準:

// 無返回值
private async Task TaskWithoutReturn() {
    await Task.Delay(1000); // 非阻塞等待
    Interlocked.Increment(ref _count);
}

// 有返回值
private async Task TaskWithReturn() {
    await Task.Delay(1000);
    return Interlocked.Increment(ref _count);
}

// 並行執行多個 Task
await Task.WhenAll(TaskWithoutReturn(), TaskWithoutReturn(), TaskWithoutReturn());

// 不等待直接啟動(Fire-and-forget)
TaskWithoutAwait(); // 編譯器警告 CS4014,需刻意忽略

核心優勢: 線性程式碼結構、統一例外處理、自然的控制流、豐富的組合 API(WhenAll、WhenAny、Delay、FromResult 等)。

WinRT 非同步介面與 Task 雙向轉換

IAsyncInfo → Task:AsTask 擴展方法

System.WindowsRuntimeSystemExtensions.AsTask 將 WinRT 非同步操作轉為 Task,支援取消權杖傳遞:

var action = AsyncInfo.Run(token => Task.Run(() => {
    token.WaitHandle.WaitOne(3000);
    token.ThrowIfCancellationRequested();
    return 100;
}, token));

// 轉換為 Task,支援 CancellationToken
var task = action.AsTask(cts.Token);
int result = await task; // 自然 await

Task → IAsyncInfo:AsAsyncAction/AsAsyncOperation

將 Task 包裝為 WinRT 介面,供 WinRT 元件或 JavaScript 呼叫:

var task = Task.Run(() => {
    cts.Token.WaitHandle.WaitOne(3000);
    cts.Token.ThrowIfCancellationRequested();
    return 100;
}, cts.Token);

// 轉換為 IAsyncOperation
IAsyncOperation operation = task.AsAsyncOperation();
int result = await operation; // WinRT 消費者可直接 await

關鍵差異: Task 取消機制完善(CancellationToken),WinRT 介面取消較簡單(Cancel() 方法)。轉換時取消語意可能不完全對應。

模式對比總結

維度APM (IAsyncResult)EAP / WinRTTAP (Task + async/await)
程式碼風格回呼巢狀事件訂閱線性同步風格
例外處理分散在 EndXxxCompleted 事件參數try/catch 自然捕獲
取消支援無標準IAsyncInfo.Cancel()CancellationToken 完整體系
組合操作極其困難手動協調WhenAll/WhenAny 等豐富 API
進度回報自行實作WithProgress 介面IProgress<T> 標準介面
適用場景舊版 API 相容WinRT 元件互操作現代 .NET 應用開發首選

實戰建議

  1. 新代碼全面採用 async/await + Task: 可讀性、維護性、效能最優。
  2. 呼叫 WinRT API 直接 await: 編譯器自動處理 IAsyncInfo 轉換,無需手動 AsTask。
  3. 編寫 WinRT 元件時: 公開方法回傳 WinRT 介面(IAsyncAction 等),內部實現用 Task 並 .AsAsyncOperation() 輸出。
  4. 避免同步阻塞: 絕不在 UI 線程 .Result、.Wait()、.GetResults(),死鎖高風險。
  5. ConfigureAwait(false): 非 UI 程式碼庫中預設使用,避免不必要的內文切換。

理解三代非同步模型的演進脈絡與轉換技術,能讓你在 Windows 8 Store Apps 開發中游刃有餘地處理新舊代碼互操作與現代化重構。

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