Task.Run 和 Task.Factory.StartNew 區別
阿新 • • 發佈:2018-12-19
Task.Run
是在 dotnet framework 4.5 之後才可以使用, Task.Factory.StartNew
可以使用比 Task.Run
更多的引數,可以做到更多的定製。
可以認為 Task.Run
是簡化的 Task.Factory.StartNew
的使用,除了需要指定一個執行緒是長時間佔用的,否則就使用 Task.Run
建立新執行緒
下面來告訴大家使用兩個函式建立新的執行緒
Task.Run(() => { var foo = 2; });
這時 foo 的建立就在另一個執行緒,需要知道 Task.Run 用的是執行緒池,也就是不是呼叫這個函式就會一定建立一個新的執行緒,但是會在另一個執行緒執行。
Task.Factory.StartNew(() => { ar foo = 2; });
可以看到,兩個方法實際上是沒有差別,但是Task.Run
比較好看,所以推薦使用Task.Run
。
等待執行緒
建立的執行緒,如果需要等待執行緒執行完成在繼續,那麼可以使用 await 等待
private static async void SeenereKousa() { Console.WriteLine("開始 執行緒"+Thread.CurrentThread.ManagedThreadId); await Task.Run(() => { Console.WriteLine("進入 執行緒" + Thread.CurrentThread.ManagedThreadId); }); Console.WriteLine("退出 執行緒"+Thread.CurrentThread.ManagedThreadId); }
但是需要說的是這裡使用 await 主要是給函式呼叫的外面使用,上面程式碼在函式裡面使用 await 函式是 void 那麼和把程式碼放在 task 裡面是相同
private static async void SeenereKousa() { Console.WriteLine("開始 執行緒"+Thread.CurrentThread.ManagedThreadId); await Task.Run(() => { Console.WriteLine("進入 執行緒" + Thread.CurrentThread.ManagedThreadId); Console.WriteLine("退出 執行緒"+Thread.CurrentThread.ManagedThreadId); }); }
但是如果把 void 修改為 Task ,那麼等待執行緒才有用
除了使用 await 等待,還可以使用 WaitAll 等待
Console.WriteLine("開始 執行緒" + Thread.CurrentThread.ManagedThreadId); var t = Task.Run(() => { Console.WriteLine("進入 執行緒" + Thread.CurrentThread.ManagedThreadId); }); Task.WaitAll(t); Console.WriteLine("退出 執行緒" + Thread.CurrentThread.ManagedThreadId);
使用 WaitAll 是在呼叫 WaitAll 的執行緒等待,也就是先線上程 1 執行,然後非同步到 執行緒2 執行,這時執行緒1 等待執行緒2執行完成再繼續,所以輸出
開始 執行緒1
進入 執行緒2
退出 執行緒1
長時間執行
兩個函式最大的不同在於 Task.Factory.StartNew
可以設定執行緒是長時間執行,這時執行緒池就不會等待這個執行緒回收
Task.Factory.StartNew(() => { for (int i = 0; i < 100; i++) { var foo = 2; } Console.WriteLine("進行 執行緒" + Thread.CurrentThread.ManagedThreadId); }, TaskCreationOptions.LongRunning);
所以在需要設定執行緒是長時間執行的才需要使用 Task.Factory.StartNew
不然就使用 Task.Run
呼叫 Task.Run(foo)
就和使用下面程式碼一樣
Task.Factory.StartNew(foo, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);