System.Threading.Tasks
?是 .NET 中任務并行庫(Task Parallel Library, TPL)的核心組件,它提供了基于任務的異步編程模型,是現代 .NET 并發編程的基礎。
設計原理
1. 核心目標
-
抽象并發工作:將并發操作抽象為"任務"概念
-
資源高效利用:自動管理線程池資源
-
組合性:支持任務鏈式操作和組合
-
取消支持:內置取消操作機制
-
狀態跟蹤:提供任務生命周期管理
2. 關鍵組件
-
Task/Task<T>:表示異步操作的核心類
-
TaskScheduler:控制任務如何、何時被執行
-
TaskFactory:提供創建和啟動任務的便捷方法
-
CancellationToken:任務取消機制
-
TaskCompletionSource:手動控制任務生命周期
3. 架構層次
-
用戶層:開發者直接使用的Task API
-
調度層:TaskScheduler管理任務執行
-
線程池層:實際執行工作的底層線程池
典型用法示例
示例1:基礎異步任務
// 創建并運行簡單任務
Task.Run(() =>
{Console.WriteLine("任務在后臺線程執行");Thread.Sleep(1000); // 模擬工作Console.WriteLine("任務完成");
});// 帶返回值的任務
Task<int> calculateTask = Task.Run(() =>
{Thread.Sleep(500);return 42; // 計算結果
});// 等待任務完成并獲取結果
int result = await calculateTask;
Console.WriteLine($"計算結果: {result}");
應用場景:CPU密集型后臺計算,不阻塞UI線程。
示例2:任務組合與延續
// 創建三個任務
Task<string> task1 = Task.Run(() => "Hello");
Task<string> task2 = Task.Run(() => "World");
Task<int> task3 = Task.Run(() => 2023);// 等待所有任務完成
await Task.WhenAll(task1, task2, task3);// 使用結果組合輸出
Console.WriteLine($"{task1.Result} {task2.Result} {task3.Result}");// 任務延續
Task continuation = task1.ContinueWith(t =>
{Console.WriteLine($"前一個任務的結果: {t.Result}");
}, TaskContinuationOptions.OnlyOnRanToCompletion);
應用場景:并行執行多個獨立操作,然后合并結果或執行后續操作。
示例3:高級任務控制
// 使用TaskCompletionSource手動控制任務
var tcs = new TaskCompletionSource<string>();// 模擬異步回調
Timer timer = new Timer(_ =>
{try{// 模擬工作string result = DateTime.Now.ToString();tcs.SetResult(result); // 手動完成任務}catch (Exception ex){tcs.SetException(ex); // 手動設置異常}
}, null, 1000, Timeout.Infinite);// 等待任務完成
try
{string timeString = await tcs.Task;Console.WriteLine($"當前時間: {timeString}");
}
catch (Exception ex)
{Console.WriteLine($"任務失敗: {ex.Message}");
}
應用場景:將基于回調的異步API轉換為基于任務的異步模式(TAP)。
示例4:取消任務
var cts = new CancellationTokenSource();
CancellationToken token = cts.Token;// 創建可取消的任務
Task longRunningTask = Task.Run(() =>
{for (int i = 0; i < 100; i++){token.ThrowIfCancellationRequested(); // 檢查取消請求Thread.Sleep(100); // 模擬工作Console.WriteLine($"進度: {i}%");}
}, token);// 3秒后取消任務
cts.CancelAfter(3000);try
{await longRunningTask;
}
catch (OperationCanceledException)
{Console.WriteLine("任務被取消");
}
應用場景:長時間運行的操作需要提供取消功能。
核心概念深入
1. 任務狀態機
任務有以下幾種狀態:
-
Created
:已創建但未調度 -
WaitingForActivation
:等待激活 -
WaitingToRun
:已調度但未開始執行 -
Running
:正在執行 -
WaitingForChildrenToComplete
:等待子任務完成 -
RanToCompletion
:成功完成 -
Canceled
:被取消 -
Faulted
:因異常失敗
2. 任務調度策略
-
線程池調度器:默認調度器,使用線程池線程
-
同步上下文調度器:在特定同步上下文(如UI線程)執行
-
自定義調度器:可繼承TaskScheduler實現特殊調度邏輯
3. 異常處理
任務中的異常會被捕獲并存儲在?Task.Exception
?屬性中,當等待任務或訪問Result屬性時,這些異常會被重新拋出。
Task faultyTask = Task.Run(() => throw new InvalidOperationException("出錯了"));try
{await faultyTask;
}
catch (InvalidOperationException ex)
{Console.WriteLine($"捕獲到異常: {ex.Message}");
}
最佳實踐
-
避免Task.Wait和Task.Result:可能導致死鎖,優先使用await
-
合理使用ConfigureAwait:庫代碼應使用ConfigureAwait(false)
-
注意任務生命周期:長時間運行的任務應考慮取消支持
-
避免過度并行化:太多并行任務會導致線程池饑餓
-
正確處理異常:確保所有任務異常都被處理
性能考慮
-
任務創建開銷:輕量級但非零成本,高頻場景考慮對象池
-
線程池壓力:大量短任務可能導致線程池頻繁調整
-
同步上下文:不必要地回到原始上下文會影響性能
System.Threading.Tasks
?提供了強大而靈活的并發編程模型,是現代 .NET 應用程序中處理異步和并行操作的首選方式。