【.NET】- Task.Run 和 Task.Factory.StartNew 區別


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);

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM