假設我們有一個涉及IO操作的方法 (讀取資料庫),這個方法支援以同步或者非同步的方式執行。
同步方式
IOMethod()
非同步方式
BeginIOMethod() EndIOMethod()
接下來我都用 Task 來包裝這兩個方法。
- public static void Main()
- {
- var task1 = Task.Factory.StartNew(() => { IOMethod(); });
- task1.Wait();
-
- var task2 = Task.Factory.FromAsync(BeginIOMethod, EndIOMethod, ... );
- task2.Wait();
- }
從資源利用率這個角度看,它們到底有什麼不同?
回答區
svick
我就從第一種說起吧。
- var task = Task.Factory.StartNew(() => { IOMethod(); });
- task.Wait();
你這種寫法會阻塞兩個執行緒:
呼叫執行緒
這個很好理解,因為你用了 task.Wait()
這個阻塞版本。
執行緒池執行緒
IOMethod
方法最終會被安排到執行緒池工作執行緒上,一直到該方法執行完畢。
接下來我們聊一下第二種方式:
- var task = Task.Factory.FromAsync(BeginIOMethod, EndIOMethod, ... );
- task.Wait();
這種寫法會阻塞一個執行緒
呼叫執行緒
這個很好理解,你用了 Wait()
方法。
這裡我有點疑惑,既然你都用了非同步IO,為何還要用 Wait()
方法呢?可以將 Wait()
改成 await
關鍵詞,從而實現 0 阻塞,這不是更好嗎?比如下面這樣:
- var task = Task.Factory.FromAsync(BeginIOMethod, EndIOMethod, ... );
- await task;
當然如果你的項目是 .NET 4.0
的話,可以用 ContinueWith
替代,同樣也可以實現 0 阻塞。
- var task = Task.Factory.FromAsync(BeginIOMethod, EndIOMethod, ... );
- task.ContinueWith(() => /* rest of the method here */);
點評區
我感覺 svick
大佬介紹的非常到位,入木三分,如果再輔以 windbg 看看 threadpool 的情況會更好,學習了。
沒有留言:
張貼留言