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

Windows 8 Store Apps 非同步程式設計:IAsyncAction、IAsyncOperation 與進度回報完整指南

     編輯:關於.NET

前言

Windows Runtime (WinRT) 以非同步為核心設計理念,所有可能超過 50ms 的 API 均為非同步。WinRT 定義了四種標準非同步介面,構成非同步程式設計的基石。本文深入解析 IAsyncAction、IAsyncOperation<TResult>、IAsyncActionWithProgress<TProgress>、IAsyncOperationWithProgress<TResult, TProgress> 的特性、建立方式與進階用法。

四大非同步介面總覽

介面返回值進度回報典型用途
IAsyncAction無無單純非同步動作(如寫入檔案、網路請求)
IAsyncOperation<TResult>有無帶結果的非同步運算(如計算、查詢)
IAsyncActionWithProgress<TProgress>無有長時間動作需進度回報(如下載、渲染)
IAsyncOperationWithProgress<TResult, TProgress>有有帶結果且需進度的複雜操作(如 SyndicationClient)

所有介面均繼承自 IAsyncInfo,提供 Cancel()、Close()、ErrorCode、Id、Status 等共同成員。

建立非同步操作:AsyncInfo.Run 工廠方法

System.Runtime.InteropServices.WindowsRuntime.AsyncInfo 提供靜態工廠方法,將 Task 或委派包裝為 WinRT 標準介面:

// IAsyncAction:無返回、無進度
public IAsyncAction CreateAction() {
    return AsyncInfo.Run(token => Task.Run(() => {
        token.WaitHandle.WaitOne(3000);
        token.ThrowIfCancellationRequested();
    }, token));
}

// IAsyncOperation:有返回、無進度
public IAsyncOperation CreateOperation(int x, int y) {
    return AsyncInfo.Run(token => Task.Run(() => {
        token.WaitHandle.WaitOne(3000);
        token.ThrowIfCancellationRequested();
        return x * y;
    }, token));
}

// IAsyncActionWithProgress:無返回、有進度
public IAsyncActionWithProgress CreateActionWithProgress() {
    return AsyncInfo.Run((token, progress) => Task.Run(() => {
        for (int p = 0; p <= 100; p++) {
            token.WaitHandle.WaitOne(100);
            token.ThrowIfCancellationRequested();
            progress.Report(p); // 回報進度 0-100
        }
    }, token));
}

// IAsyncOperationWithProgress:有返回、有進度
public IAsyncOperationWithProgress CreateOperationWithProgress() {
    return AsyncInfo.Run((token, progress) => Task.Run(() => {
        for (int p = 0; p <= 100; p++) {
            token.WaitHandle.WaitOne(100);
            token.ThrowIfCancellationRequested();
            progress.Report(p);
        }
        return "完成";
    }, token));
}

消費非同步操作:完成事件與進度事件

WinRT 非同步模式採用事件基礎模式(EAP),而非 await:

var action = CreateActionWithProgress();

// 完成事件
action.Completed = (asyncInfo, status) => {
    switch (status) {
        case AsyncStatus.Completed:
            Debug.WriteLine("成功完成");
            break;
        case AsyncStatus.Canceled:
            Debug.WriteLine("已取消");
            break;
        case AsyncStatus.Error:
            Debug.WriteLine($"錯誤: {asyncInfo.ErrorCode}");
            break;
    }
};

// 進度事件(僅 WithProgress 介面)
action.Progress = (asyncInfo, progressValue) => {
    Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => {
        ProgressBar.Value = progressValue;
    });
};

// 取消操作
action.Cancel();

與 async/await 的互操作

雖然 WinRT 原生使用事件模式,但 await 可直接消費這四種介面,編譯器自動處理轉換:

// 直接 await IAsyncAction
await CreateAction();

// await IAsyncOperation 獲取結果
int result = await CreateOperation(10, 20);

// await 帶進度操作(需手動訂閱進度事件)
var op = CreateOperationWithProgress();
op.Progress = (_, p) => UpdateProgress(p);
string result = await op;

注意: await 會捕獲當前 SynchronizationContext,UI 線程上預設回到 UI 線程。使用 .ConfigureAwait(false) 可避免切換回 UI 線程,提升效能。

進階:取消權杖與異步協調

CancellationToken 串聯 Task 與 WinRT 非同步操作:

var cts = new CancellationTokenSource();
var action = AsyncInfo.Run(token => Task.Run(() => {
    for (int i = 0; i < 100; i++) {
        token.WaitHandle.WaitOne(100);
        token.ThrowIfCancellationRequested(); // 拋出 OperationCanceledException
    }
}, token));

// 3 秒後自動取消
cts.CancelAfter(TimeSpan.FromSeconds(3));

try {
    await action;
} catch (OperationCanceledException) {
    // 處理取消
}

實際應用場景對照

  • IAsyncAction: StorageFile.DeleteAsync()、MediaCapture.StartRecordToStorageFileAsync()
  • IAsyncOperation<T>: FileOpenPicker.PickSingleFileAsync()、HttpClient.GetStringAsync()
  • IAsyncActionWithProgress: 自訂長時間渲染、批次處理
  • IAsyncOperationWithProgress: SyndicationClient.RetrieveFeedAsync()、大檔案下載與解析

最佳實踐總結

  1. 優先使用 async/await: 程式碼可讀性最高,例外處理自然。
  2. 長時間操作必須支援取消: 定期檢查 token.ThrowIfCancellationRequested()。
  3. 進度回報使用 IProgress<T>: 解耦進度消費者與生產者,支援跨線程 UI 更新。
  4. 釋放資源: 實作 IDisposable 的非同步操作用完呼叫 Close()。
  5. 避免同步阻塞: 絕不在 UI 線程呼叫 .GetResults() 或 .Wait(),務必 await。

掌握 WinRT 四大非同步介面的建立、消費與互操作,是開發流暢、回應迅速 Windows 8 Store Apps 的核心技能。

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