2016-11-12 134 views
-1

我很清楚不建議使用異步同步。原因是有道理的。異步同步執行更好?

設置Web API控制器時,我使用和不使用異步同步進行測試。我使用服務中的數據和一個按鈕來設置表格,該按鈕將同時更新每個項目的單個請求到服務。令我驚訝的是,沒有異步同步的設置似乎每次處理五個批次;異步同步完成更新快速且單獨:整個批次的完成時間比單批次花費的時間多一點。

總之,對於一個Web API控制器:

  • 異步同步上出現運行所有並聯請求。
  • 正常代碼運行一次並行請求最多五(5)個請求。

鑑於重複的Q &作爲和集體文獻,我的結論使用異步同步性能一定是有缺陷的。 你能解釋我看到的行爲嗎?我懷疑答案在於我如何設置我的本地系統,但我會欣賞那些比我更懂行的人。


「異步過同步」將是這樣的:

public async Task SyncAsync() 
{ 
    return new Task(() => Thread.Sleep(2000)); 
} 

根據sources

這是毫無意義的,你只是卸載從一個線程池工作線程到另一個。

所以我還不如寫:

public void Sync() 
{ 
    Thread.Sleep(2000); 
} 
+0

我的問題不清楚嗎?我的答案是否已經存在於別的地方?或者我只是畫一張關閉和選舉票,因爲提到「異步同步」會讓你感到厭惡? – ricksmt

+0

「異步同步」是什麼意思? – Enigmativity

+4

你可以把一些示例代碼? – dotnetstep

回答

1

更新1 你想說的是異步執行的所有請求平行的,但在那種情況下,將轉移工作線程池來線。

  1. 我只好解釋以下爲好,但明白,所有的請求,對於一些API調用或在這種情況下,一些I/O調用您服務更多的請求,但在同步的情況下,你唯一的服務器5請求作爲當前線程是塊。

在上面我認爲線程池有5

capicity所以,當6請求到來,將在同步的情況下等待。如果I/O線程池中的所有5個請求的異步都對服務器6請求有空閒線程。這樣它增加了應用程序的吞吐量。

此外,你必須確保任務不是線程。任務和線程是不同的。


我一般在這裏和我在我的發展過程中測量的最好。

  1. 異步/等待不是改善性能的銀彈。你必須正確實施它。當執行的任務是基於I/O時,如某些數據庫調用,Web服務調用或文件系統調用,應使用Async/Await。在這種情況下,由於I/O操作不需要線程,因此它可以帶來好處,並且它不必阻塞一個線程。

  2. 如果您在異步/等待中執行CPU密集型任務,那麼它不會給您帶來性能上的好處。

  3. 此外,你必須在各種負載下測試你的應用程序。就像如果你已經託管你的應用程序IIS並且在本地測試了debug,那麼總是會有更少的資源消耗,那麼你會覺得Sync是好的,因爲它們獲得免費資源,但是當你增加負載時(像許多用戶一樣),那麼它在Sync中創建瓶頸,就好像它不會找到空閒線程一樣,即使內部IIS線程正在等待I/O完成,請求也不會提供服務。

https://msdn.microsoft.com/en-us/magazine/hh456402.aspx

https://msdn.microsoft.com/en-us/magazine/jj991977.aspx

+0

我不確定你瞭解我的問題。我會嘗試對其進行重新說明。下週我將不得不在下一個MCV上工作:我的時間不夠了。 – ricksmt

+0

您的更新表明您現在與我擁有相同的理解。我想知道5的線程池來自哪裏,爲什麼它不同於它正在卸載的線程池。 – ricksmt

0

我從你們的討論看到dotnetstep你正試圖組建一個MVC應用程序,但我不認爲我需要看到的是回答你的問題。 Dotnetstep的回答是正確的,但我想詳細說明您在評論中提出的一些其他問題。

我想明白其中的5線程池是從

這只是一個任意數量dotnetstep選擇了未來。該數字將來自web.config文件的processModel> maxWorkerThreads部分。這是ASP.NET可以處理的併發執行請求的數量。這個數字鼓勵開發人員儘量減少請求的執行時間。例如,如果這個數字是5,那麼ASP.NET可以同時處理5個請求。但是如果請求依賴於其他一些I/O操作會發生什麼?如果你需要撥打網絡服務怎麼辦?

在「Sync」場景中,當Request1進入並調用Web服務時,Request1的線程將等待,直到Web服務的響應已經發生。請求2,請求3,請求4和請求5相同。當請求6進入時,服務器將返回HTTP 503響應(「服務不可用」),因爲所有5個線程都在等待Web服務響應。此時,您的服務器無法處理任何其他請求,直到其中一個請求完成並且該線程已返回到線程池。

在「Async」場景中,Request1進入並調用Web服務,Request1的線程不會等待來自Web服務的響應,而是立即返回到線程池。請求2,請求3,請求4和請求5相同。當請求6進入時,服務器具有全部5個線程(假設沒有任何web服務調用已經返回)來處理請求。這是「異步」的好處,因爲它不會阻止你的線程。這樣你可以同時處理更多的請求。

正如你可以清楚地看到這一切取決於你在請求中做什麼。如果請求正在進行需要純粹CPU關注的工作(CPU密集型工作),那麼異步不會對您有所幫助,因爲無論是異步還是同步,CPU都被佔用,並且別無其他。因此,您的請求將不得不等待。注意你在Async操作中正在做的事情。如果所有你做的用於測試目的是:

Thread.Sleep(2000); 

那麼你的線程仍然保持佔領無論是同步或異步(只有一個辦法,線程可以入睡,不能入睡,並在同一時間做的工作通過返回到線程池)。

做一些真正異步的事情,例如,從大文件中讀取,你會看到真正的好處或異步與同步。

以及爲什麼它不同於它正在卸載的線程池。

執行I/O請求的線程與提供這些ASP請求的線程不同。在某些情況下,它甚至不是同一臺機器,例如,如果您調用另一臺機器上的Web服務或從某個其他機器上的文件中讀取數據......您就明白了。

更新1:

一點的詳細信息,可以是有益的是,當你有這樣的代碼:

return new Task(() => Thread.Sleep(2000)); 

如果上面的代碼是由Request1的線程,它就會被卸載到另一個線程(請求1,請求2,請求3或請求4)。而另一個線程會睡覺。所以基本上它會讓你付出更多的代價,因爲你切換了上下文,但是你沒有得到任何回報。因此,由於此處的上下文切換,您的異步版本將比您的同步版本慢。

此外,請記住,無論是同步還是異步(它不會更快),客戶端必須等待的時間幾乎相同。唯一的好處是你的服務器可以處理更多的請求。工作仍然需要以某種方式完成(同步或異步)。