2011-05-13 125 views
17

我很開心與System.Threading.Tasks一起工作。然而,我看到的許多代碼示例看起來像這樣:我是否需要處置任務?

Dim lcTask = Task.Factory.StartNew(Sub() DoSomeWork()) 
Dim lcTaskLong = Task.Factory.StartNew(Sub() DoSomeWork(), TaskCreationOptions.LongRunning) 
Task.WaitAll(lcTask, lcTaskLong) 

這就是樣本的範圍。
任務執行IDisposable,所以顯然我應該把它們處理掉,但是如果我只是想「火與忘」呢?

如果我不處理,我會泄漏線程/句柄/內存/業障嗎? 我是否在使用任務「錯誤」? (應該只是使用委託並單獨留下任務?)

我可以在ContinueWith()中處理嗎? (這似乎是玩俄羅斯輪盤賭。)

回答

18

雖然拇指的正常規則是隨時撥打Dispose()所有IDisposable實現,TaskTask<T>往往是一個情況下,最好讓終結照顧這。

Task執行IDisposable的原因主要是由於內部的WaitHandle。這是允許任務繼續正常工作所必需的,並且只有在任務繼續時才能使用。如果沒有延續,任務的Dispose方法沒有實際效果 - 所以在這種情況下,這不是必需的。

這就是說,在大多數情況下,如果存在任務延續,那麼以正確調用Dispose()的方式編寫代碼通常非常非常困難。使用語句通常不適用於Task實例,因爲Task調用本質上通常是異步的。很容易過早地處理該任務,特別是在使用using語句時。

如果在您的情況下,保持對任務的引用並正確調用Dispose()相對簡單,我會這樣做。但是,如果這會導致您的邏輯變得複雜得多,我通常會假裝Task不是IDisposable,並允許在任務的終結器中清理它。

欲瞭解更多詳情,我建議reading this thread on the MSDN forums其中Stephen Toub描述了Task爲什麼實現IDisposable的細節,並提供了與上述建議類似的指導。

+1

And ... \t \t [CodeAnalysis.SuppressMessage(「Microsoft.Reliability」,「CA2000」,Justification =「http://stackoverflow.com/questions/5985973/do-i-need-to-dispose-of -a-task「)] – GarethOwen 2012-06-18 15:03:18

+2

根據您鏈接到的Stephen Toub線程判斷,我認爲當您說」需要[等待句柄]以允許任務繼續正常工作並且僅在存在如果沒有延續,任務的Dispose方法沒有實際效果......「但根據Toub的說法,」Task.Dispose的存在是由於任務可能包裝了一個事件句柄......如果你正在做的正在使用continuation,那個事件句柄永遠不會被分配,並且Dispose的值會大大減少。「即與上面暗示的相反。 – 2015-09-06 19:14:58

相關問題