Task.Factory.StartNew 和 Task.Run 到底有什么区别?
前言
Task.Factory.StartNew 和 Task.Run 都可以創建 Task:
Task.Factory.StartNew(()?=>?{?Console.WriteLine("Task.Factory.StartNew");?});Task.Run(()?=>?{?Console.WriteLine("Task.Run");?});那它們之間有什么區別呢?
實現代碼
查看這 2 個方法的內部實現,其內部實現邏輯其實是一樣的,只是傳的默認參數不同:
//Task.Factory.StartNew public?Task?StartNew(Action?action) {Task??currTask?=?Task.InternalCurrent;return?Task.InternalStartNew(currTask,?action,?null,?m_defaultCancellationToken,?GetDefaultScheduler(currTask),m_defaultCreationOptions,?InternalTaskOptions.None); } //Task.Runpublic?static?Task?Run(Action?action) {return?Task.InternalStartNew(null,?action,?null,?default,?TaskScheduler.Default,TaskCreationOptions.DenyChildAttach,?InternalTaskOptions.None); }最關鍵的參數區別是 Task.Run 傳入了 TaskCreationOptions.DenyChildAttach。
那這個參數有什么用呢?
DenyChildAttach
查看官方文檔[1]的解釋,DenyChildAttach 的作用是阻止子任務附加到其父任務:
設想下從 Task 對象調用第三方庫組件的應用。如果第三方庫組件也創建一個 Task 對象,并指定 TaskCreationOptions.AttachedToParent 以將其附加到父任務中,則子任務中出現的任何未經處理的異常將會傳播到父任務。這可能會導致主應用中出現意外行為。
創建代碼驗證一下:
Stopwatch?stopwatch1?=?new?Stopwatch(); stopwatch1.Start(); var?task1?=?Task.Factory.StartNew(()?=> {Run();Console.WriteLine("Task.Factory.StartNew"); });await?task1; stopwatch1.Stop(); Console.WriteLine(stopwatch1.ElapsedMilliseconds);Stopwatch?stopwatch2?=?new?Stopwatch(); stopwatch2.Start(); var?task2?=?Task.Run(()?=> {Run();Console.WriteLine("Task.Run"); });await?task2; stopwatch2.Stop(); Console.WriteLine(stopwatch2.ElapsedMilliseconds);Run 方法代表執行相同的第三方庫組件調用,內部使用了 AttachedToParent:
private?static?void?Run() {Task.Factory.StartNew(()?=>{Thread.Sleep(1000);Console.WriteLine("Run");},?TaskCreationOptions.AttachedToParent); }運行程序,你將會看到類似的如下輸出:
Task.Factory.StartNew Run 1080 Task.Run 1 Run使用 Task.Factory.StartNew 必須等待 AttachedToParent 任務執行完,而 Task.Run 不必。
結論
一般情況下,盡量使用 Task.Run,如果需要更精細地控制任務的行為,比如 TaskCreationOptions, 才使用 Task.Factory.StartNew。
想了解更多內容,請關注我的個人公眾號”My IO“
參考資料
[1]
官方文檔: https://docs.microsoft.com/zh-cn/dotnet/standard/parallel-programming/attached-and-detached-child-tasks
總結
以上是生活随笔為你收集整理的Task.Factory.StartNew 和 Task.Run 到底有什么区别?的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C# 利用.NET 升级助手将.NET
- 下一篇: 【Blog.Core开源】框架集成部门权