.NET - Task.Run vs Task.Factory.StartNew
阿新 • • 發佈:2020-08-25
> 翻譯自 Stephen Toub 2011年10月24日的博文[《Task.Run vs Task.Factory.StartNew》](https://devblogs.microsoft.com/pfxteam/task-run-vs-task-factory-startnew/),Stephen Toub 是微軟平行計算平臺團隊的首席架構師。
在 *.NET 4* 中,`Task.Factory.StartNew` 是安排新任務的首選方法。它有許多過載提供了高度可配置的機制,通過啟用設定選項,可以傳遞任意狀態、啟用取消,甚至控制排程行為。所有這些功能的另一面是複雜性。您需要知道什麼時候使用哪個過載、提供什麼排程程式等等。另外,`Task.Factory.StartNew` 用起來並不直截乾脆,至少對於它的一些使用場景來說還不夠快,比如它的主要使用場景——輕鬆地將工作交付到後臺處理執行緒。
因此,在 *.NET Framework 4.5 開發者預覽版* 中,我們引入了新的 `Task.Run` 方法。這決不是要淘汰 `Task.Factory.StartNew`,而是應該簡單地認為這是使用 `Task.Factory.StartNew` 而不必傳遞一堆引數的一個便捷方式。這是一個捷徑。事實上,`Task.Run` 實際是按照與 `Task.Factory.StartNew` 相同的邏輯實現的,只是傳入了一些預設的引數。當你傳遞一個 `Action` 給 `Task.Run`:
```csharp
Task.Run(someAction);
```
完全等同於:
```csharp
Task.Factory.StartNew(someAction, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);
```
通過這種方式,`Task.Run` 就可以並且應該被用於大多數通用場景——簡單地將工作交給執行緒池`ThreadPool`處理(即引數 TaskScheduler.Default 的目標)。這並不意味著 `Task.Factory.StartNew` 將不再被使用; 遠非如此,`Task.Factory.StartNew` 還有很多重要的(固然更高階)用途。你可以控制 `TaskCreationOptions` 來控制任務的行為,可以控制 `TaskScheduler` 來控制任務的排程和執行,也可以使用接收物件狀態的過載,對於效能敏感的程式碼路徑,使用該過載可以避免閉包和相應的記憶體分配。不過,對於簡單的情況,`Task.Run` 是你的朋友。
`Task.Run` 提供八個過載,以支援下面的所有組合:
1. 無返回值任務(`Task`)和有返回值任