2013-05-21 92 views
1

我有幾個執行自定義計算的計算器類。從歷史上看,這些類的方法已經通過BackgroundWorker啓動,因爲它們冗長,運行時間明智。爲什麼在線程池(通過Task.Run)上啓動的代碼比在BackgroundWorker中運行的代碼慢?

最近我正在將應用程序轉換爲在C#中使用新的異步支持,現在通過Task.Run()運行相同的方法,但我注意到它們運行速度慢了大約5-7%(這是在我的應用程序大不了)。

有一個明顯/預期的原因,爲什麼一個線程池線程比BackgroundWorker做的慢?

我沒有對計算邏輯做任何修改;我只是將計算方法傳遞給Task.Run()(並等待它),然後將其提供給BackgroundWorker,所以我相當肯定我自己沒有引入任何更改,以減少速度。

+3

請張貼代碼。可能是任何事情。 – usr

回答

3

如果您的計算過於細化,我期望看到類似這樣的結果。

有一個開銷Task.Run:首先,有線程池隊列,必須導航;其次,執行環境的編組(出於安全原因);第三,有一個包裝操作捕捉任何異常。

如果您在自己的隊列中使用單個BGW,那麼您的隊列更簡單(可能更快)。執行上下文的編組僅發生一次(對於整個BGW),並且每個操作周圍都沒有包裝(只有一個圍繞BGW.DoWork的包裝)。

現在,如果您每次計算使用一個BGW,然後我期望Task.Run會更快。

作爲替代方案,請查看任務並行庫。對於計算,我推薦Parallel類型(或PLINQ)通過Task.Run,除非您確實需要動態並行性。如果您需要更多信息,請閱讀Parallel Programming with Microsoft .NET,特別是this image(但請注意,「期貨」最好用async/await表示,「管道」用TPL數據流表示更好)。

+0

我也有過這種懷疑。這可能是導致此問題的代碼設計錯誤。我希望OP會發布一些代碼,以便我們可以確定地知道。 – usr

+0

我會試着想出一個簡潔的帖子,提供更多的細節。現在,讓我添加這些位: 我不是100%確定斯蒂芬的意思是「太細粒度」。我假設他問他們是否是非常快速的方法,這些方法會被調用很多。如果是這樣,我的答案是「否」..這些是單方法調用,如「等待Task.Run(Calculator.Run())」,其中Run方法可能會運行幾分鐘或幾天。在那次行動中,我的應用程序沒有同時做其他任何事情。 –

+0

我不時地懷疑await/async方法是否最適合我的需求(因爲這些calc可以運行一個很長的時間),但是語法非常吸引人,我沒有使用TPL進行調查非常多。 –

相關問題