2014-06-18 92 views
4

我有這個ASP MVC調用是異步的,因爲它需要做一個異步調用。我注意到有幾個慢速同步調用(例如db訪問)。該方法需要使所有返回的數據可用才能繼續。我應該使用Task.Run包裝慢速呼叫嗎?

我想用Task.Run包裝同步調用並等待所有這些調用。

包裝慢速同步呼叫有意義嗎?如果只有同步呼叫會怎麼樣?

回答

0

如果任務是獨立的(不依賴於來自其他任務的數據),並且可以獨立執行,那麼是的,通過所有方式來異步執行它們。如果他們是實體框架,並且它是版本6,那麼它提供Async方法來調用,並且您不必將它們包裝在Task.Run中。

即使這些任務不是獨立的,您仍然可以通過某種方式對它們進行排序,以使它們在執行時更高效。

是否使用Task.Run然而是一個重要的區別。 Task.Run將使用一個ThreadPool線程,如果它正在做同步操作將阻塞,並因此減少可用於您的應用程序的ThreadPool數量。如果你有很多用戶,並且你正在執行很多任務,這可能是一個問題。

嘗試查找異步API而不是使用Task.Run。

5

不要使用Task.Run來並行化服務器端代碼中的工作,除非您希望同時服務的客戶端請求數量非常少。否則,您可能會加快處理單個請求的速度,但是當有許多用戶時,您的Web應用程序的可伸縮性會受到影響。

+0

是不是使用async/await來允許保存當前線程而不是等待處理請求?如果需要並行任務,那麼他應該使用TPL,但使用TAP應該有助於擴展性而不是阻礙它。 –

+0

@RyanPeters,的確如此,但在服務器端上下文中,您通常只對自然異步API使用TAP(請檢查Stephen Cleary的[「沒有線程」](http://blog.stephencleary.com/2013/11 /there-is-no-thread.html))。這樣,HTTP請求的初始線程被釋放到池中,然後可以服務於另一個HTTP請求。但是如果你使用'Task.Run',你不會釋放線程。至於包裝一個單一的同步調用,它根本沒有意義 - 你可以在當前線程上做。至於並行打包多個調用 - 會傷害可伸縮性。 – Noseratio

+1

對於客戶端UI應用程序,情況可能會有所不同,您不關心可伸縮性,而是關心保持UI線程響應。 – Noseratio

1

要試着擴展@Noseratio,旋轉線程來「加快」同步工作的規模非常糟糕。

一個重要的事情要記住的是,在ASP.NET內使用Task.Run是非常危險的,因爲運行時不知道你排隊的工作需要完成,IIS可能會嘗試不時地回收你的應用程序,這將導致工作無意中突然發生。

如果您使用的是.NET Framework 4.5.2,則通過HostingEnvironment.QueueBackgroundWorkItem提供解決方案。您可以在Fire and Forget on ASP.NET中閱讀更多內容。如果不是,請閱讀Returning Early from ASP.NET Requests以獲取自定義實現。這些優秀的文章都是由@StephanCleary

+1

我不認爲作者正在談論在這裏早點回來。你在談論火災和遺忘,或異步無效的方法,這可能會導致你正在談論的問題。在這種情況下,他需要工作的結果,因此他必須等待他們完成,工作流程不會被回收。因此,以這種方式使用Task.Run沒有「危險」,儘管@Noseratio提到它對於可伸縮性並不好。 –

+0

他正在等待這些任務,沒有理由爲什麼IIS不會試圖回收eveb,儘管他正在「等待」。我不是在談論異步無效或火災和忘記,即時通訊談論在ASP.NET內使用'Task.Run'一般 –

+1

如果主要操作線程尚未完成並正在等待,它不會回收,除非它超時。如果你不是在談論火和忘記,你爲什麼參考這兩篇文章呢? –