新聞速報

        

2023年5月19日 星期五

Task.Factory.StartNew 和 Task.Factory.FromAsync 有什麼區別?

假設我們有一個涉及IO操作的方法 (讀取資料庫),這個方法支援以同步或者非同步的方式執行。

  1. 同步方式

IOMethod()

  1. 非同步方式

BeginIOMethod()  EndIOMethod()

接下來我都用 Task 來包裝這兩個方法。

  1. public static void Main()
  2. {
  3.     var task1 = Task.Factory.StartNew(() => { IOMethod(); });
  4.     task1.Wait();
  5.     var task2 = Task.Factory.FromAsync(BeginIOMethod, EndIOMethod, ... );
  6.     task2.Wait();
  7. }

從資源利用率這個角度看,它們到底有什麼不同?

回答區

  • svick

我就從第一種說起吧。

  1. var task = Task.Factory.StartNew(() => { IOMethod(); });
  2. task.Wait();

你這種寫法會阻塞兩個執行緒:

  1. 呼叫執行緒

這個很好理解,因為你用了 task.Wait() 這個阻塞版本。

  1. 執行緒池執行緒

IOMethod 方法最終會被安排到執行緒池工作執行緒上,一直到該方法執行完畢。





接下來我們聊一下第二種方式:

  1. var task = Task.Factory.FromAsync(BeginIOMethod, EndIOMethod, ... );
  2. task.Wait();

這種寫法會阻塞一個執行緒

  1. 呼叫執行緒

這個很好理解,你用了 Wait() 方法。

這裡我有點疑惑,既然你都用了非同步IO,為何還要用 Wait() 方法呢?可以將 Wait() 改成 await 關鍵詞,從而實現 0 阻塞,這不是更好嗎?比如下面這樣:

  1. var task = Task.Factory.FromAsync(BeginIOMethod, EndIOMethod, ... );
  2. await task;

當然如果你的項目是 .NET 4.0 的話,可以用 ContinueWith 替代,同樣也可以實現 0 阻塞。

  1. var task = Task.Factory.FromAsync(BeginIOMethod, EndIOMethod, ... );
  2. task.ContinueWith(() => /* rest of the method here */);

點評區

我感覺 svick 大佬介紹的非常到位,入木三分,如果再輔以 windbg 看看 threadpool 的情況會更好,學習了。

沒有留言:

張貼留言