2015-10-08 70 views
0

在閱讀了大量有關異步等待的知識後,我只能在GUI線程(WPF/WinForms)中找到使用它的好處。如何處理異步I/O方法

它在哪些情況下減少了WCF服務中線程的創建? 程序員是否必須在服務中的每個方法上使用async-await ,方法是選擇在Web服務中實現異步等待?在充滿異步等待的服務中製作一些非異步等待方法會降低服務的效率?怎麼樣?

最後一個問題 - 有人說,使用'await Task.Run(()=> ...)'不是「真正的異步等待」。這是什麼意思?

謝謝你, 斯塔夫。

編輯:

這兩個答案都是優秀的,但即使有關如何異步等待的作品,我建議閱讀@Stephen克利回答這裏瓢解釋: https://stackoverflow.com/a/7663734/806963

以下主題都需要理解他的回答: SynchronizationContext,SynchronizationContext.Current,TaskScheduler,TaskScheduler.Current,Threadpool。

+2

'Task.Run'用於在線程池線程上執行cpu-bound代碼。真正的異步等待是關於IO限制的代碼。 –

+1

這個問題可能看起來太寬泛了,但考慮到正確的答案,它不是。整個概念可以在5段中全面清楚地解釋。 –

回答

4

服務器應用程序(如WCF)中異步/等待的真正好處是異步I/O。

當您調用同步I/O方法時,調用線程將被阻塞,等待I/O完成。該線程不能被其他請求使用,它只是等待結果。當更多請求到達時,線程池將創建更多線程來處理它們,浪費大量資源 - 內存,等待線程解除阻塞時的上下文切換...

如果使用異步IO,線程不會被阻止。在啓動異步IO操作之後,它可以再次被線程池使用。當異步操作完成時,線程池分配一個線程繼續處理請求。沒有資源浪費。

MSDN(這是關於文件I/O,但也適用於其他太)

在同步文件I/O,一個線程啓動的I/O操作,並立即進入等待狀態,直到我/ O請求已完成。執行異步文件I/O的線程通過調用適當的函數向內核發送I/O請求。如果請求被內核接受,調用線程將繼續處理另一個作業,直到內核向線程發出I/O操作完成的信號。然後中斷它當前的工作並根據需要處理來自I/O操作的數據。

現在,你可能就會明白爲什麼await Task.Run()不會給予任何好處,如果在任務中的IO同步完成。無論如何,線程都會被阻止,而不是那個叫做Task.Run()的線程。

您不需要異步實現每種方法以查看性能的改進(儘管它應該成爲一種習慣,始終以異步方式執行I/O)。

+0

我承認我認爲每個調用都不是從threadpull獲得新線程。這非常有幫助。雖然邏輯告訴我,如果我創建一個方法(方法1),返回一個任務爲其他方法來異步它(調用:await method1())它是一樣的做await Task.Run(method1())becouse method1實現返回Task.run(()=>());.所以我沒有任何好處來避免它。我正在矯正嗎? –

+1

你是對的。要正確實現異步IO而不使用.NET BCL中的現有異步方法,您必須在非常靠近操作系統的較低級別上工作。幸運的是,一切都很好地由.NET BCL處理,所以你可以等待這些方法。 –

0

它在哪些情況下減少了WCF服務中線程的創建?

如果您有一個等待IO操作(從數據庫讀取數據,調用外部Web服務......)的操作,使用async/await可以釋放您的WCF請求所在的託管線程處理。這使得該線程可用於其他請求,等待完成IO。它可以更高效地使用線程池。

很多閱讀有關異步的await之後,我只能找到在GUI線程

對於客戶應用程序是我所知道的最重要的優勢使用它的好處,因爲您比在服務器應用程序中更不可能用盡管理線程。

有人說,使用'await Task.Run(()=> ...)'不是一個「真正的異步等待」。

您分配一個新的託管線程來運行您的新任務,因此您不保存任何託管線程。

+0

如果我明白,WCF使用線程處理任何請求+任何異步等待操作?所以如果我通過返回新任務來實現我自己的異步等待 - 它並沒有真正創建一個,只使用一些線程拉線程而已? –

+0

HTTP請求由線程池處理。 IO操作在掛起時不需要線程。 –

+0

那麼你告訴我的是Async-IO opertion不在其他線程上?它的封鎖運作呢? –