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

Windows 8 Store Apps 任務平行庫:Task 基礎、多任務協調與 Parallel 平行運算

     編輯:關於.NET

前言

Task 是 .NET 任務平行庫 (TPL) 的核心抽象,代表「未來會完成的工作」。在 Windows 8 Store Apps 中,Task 基於線程池,取代傳統 Thread 成為非同步與平行運算的基石。本文系統介紹 Task 建立、取消、續作、多任務協調與 Parallel 平行運算。

Task 基礎:建立、啟動與生命週期

建立 Task 的多種方式

// 1. Task.Run:建立並立即排程(推薦)
var task1 = Task.Run(() => DoWork());

// 2. Task.Factory.StartNew:進階選項(長時間任務指定 LongRunning)
var task2 = Task.Factory.StartNew(() => DoWork(), TaskCreationOptions.LongRunning);

// 3. new Task() + Start():分離建立與啟動(罕見需求)
var task3 = new Task(() => DoWork());
task3.Start();

// 4. TaskCompletionSource:手動控制完成狀態(包裝舊 API)
var tcs = new TaskCompletionSource();
// ... 非同步操作完成時 tcs.SetResult(42) 或 tcs.SetException(ex)
Task task4 = tcs.Task;

取消機制:CancellationToken 完整流程

var cts = new CancellationTokenSource();
var token = cts.Token;

var task = Task.Run(() => {
    for (int i = 0; i < 100; i++) {
        token.ThrowIfCancellationRequested(); // 拋出 OperationCanceledException
        Thread.Sleep(100);
    }
}, token);

// 外部請求取消
cts.Cancel(); // 或 cts.CancelAfter(3000);

// 等待並處理取消
try {
    await task;
} catch (OperationCanceledException) when (token.IsCancellationRequested) {
    // 正常取消,不視為錯誤
}

續作:ContinueWith 與 await 的抉擇

ContinueWith 是底層續作 API,await 是語法糖(編譯器自動生成續作)。現代代碼優先使用 await:

// 現代風格
var result = await Task.Run(() => Compute());
UpdateUI(result);

// 續作風格(需手動切 UI 線程)
Task.Run(() => Compute())
    .ContinueWith(t => Dispatcher.RunAsync(..., () => UpdateUI(t.Result)));

ContinueWith 進階選項: TaskContinuationOptions.OnlyOnRanToCompletion、OnlyOnFaulted、OnlyOnCanceled、ExecuteSynchronously 等。

多任務協調:WhenAll、WhenAny、WaitAll

方法行為返回值典型用途
Task.WhenAll非阻塞等待全部完成Task / Task[]並行啟動多個獨立操作,全部完成後聚合結果
Task.WhenAny非阻塞等待任一完成Task / Task[]超時控制、競速模式、第一個響應者獲勝
Task.WaitAll同步阻塞等待全部void僅用於非 UI 線程、Main 方法等同步語境
Task.WaitAny同步阻塞等待任一int (索引)同步語境下的競速等待
// 並行下載多個 URL,全部完成後處理
var downloadTasks = urls.Select(url => httpClient.GetStringAsync(url)).ToArray();
string[] results = await Task.WhenAll(downloadTasks);

// 競速:3 秒內未完成則取消
var timeoutTask = Task.Delay(3000);
var completedTask = await Task.WhenAny(longRunningTask, timeoutTask);
if (completedTask == timeoutTask) cts.Cancel();

Parallel 類別:聲明式平行運算

Parallel 提供高層平行迴圈與調用,自動處理分區、負載平衡、線程池調度:

Parallel.For / ForEach

// 平行迴圈
Parallel.For(0, 1000, i => {
    ProcessItem(i);
});

// 平行 foreach(支援 Partitioner 自訂分區)
Parallel.ForEach(largeCollection, item => {
    ProcessItem(item);
});

// 區域變數避免共享狀態爭用
Parallel.For(0, n, 
    () => 0, // 區域初始化
    (i, state, local) => local + Compute(i), // 區域累加
    local => Interlocked.Add(ref total, local) // 合併
);

Parallel.Invoke

// 平行執行多個獨立 Action
Parallel.Invoke(
    () => Task1(),
    () => Task2(),
    () => Task3()
);

關鍵配置選項:ParallelOptions

var options = new ParallelOptions {
    MaxDegreeOfParallelism = 4, // 限制最大並行度
    CancellationToken = cts.Token, // 支援取消
    TaskScheduler = customScheduler // 自訂調度器
};

Parallel.ForEach(collection, options, item => { ... });

Task 與 Parallel 選擇指南

場景推薦方案理由
非同步 I/O 操作Task / await釋放線程、可擴展性最強
CPU 密集型批次處理Parallel.ForEach自動分區、負載平衡、簡潔聲明式
固定數量獨立非同步操作Task.WhenAll語意清晰、結果聚合自然
動態數量、需取消、超時控制Task + CancellationToken精細控制、組合靈活
需自訂分區、負載平衡策略Parallel + Partitioner框架級支援

避坑指南

  1. UI 線程禁用 .Result/.Wait(): 導致死鎖,務必 await。
  2. 非同步 Lambda 避免 async void: Task.Run(async () => await ...) 而非 Task.Run(async () => { await ... }) 後者編譯為 async void,例外無法捕獲。
  3. Parallel 不適合 I/O 密集: 會佔用線程池線程阻塞,改用 SemaphoreSlim 限流 + Task.WhenAll。
  4. 取消權杖傳遞: 所有可取消的非同步 API 均傳入 token,內部定期 ThrowIfCancellationRequested。
  5. 例外處理: Task.WhenAll 會拋出 AggregateException(包含所有例外),await 只拋出第一個。

熟練掌握 Task 與 Parallel 的協作模式,能讓 Windows 8 Store Apps 在保持 UI 流暢的同時,充分發揮多核心 CPU 的計算能力。

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