2015-04-01 51 views
1

我是一個非常新的編程,我正在開發我的第一個自我項目,這是我用ASP.NET MVC 5創建的論壇,我正試圖從中學習。 我在這裏和MSDN讀了很多關於MVC中的異步操作的知識,我有幾個問題我無法弄清楚。異步/等待的可伸縮動作

  1. 據我所知,IIS爲每個進程分配x個線程,例如2。每個線程都可以處理1個請求。當我將一個動作標記爲異步,並用任務包裝返回類型時,線程會分配一個工作人員來處理請求並報告IIS現在有空來處理另一個請求。所以如果一個線程可以創建3個工作者,我的行爲可以提供6個請求。對?
    據我所知,一個異步方法必須等待另一個異步方法才能真正異步,否則該方法將同步運行。所以我的問題是,什麼時候該線程分配這個工作者?當請求到來或等待的方法被調用時?

  2. 同樣,據我所知,每個異步方法都被分配給一個工作人員,所以如果我的網站有6名工作人員(來自上述問題),可以處理請求的工人數量會減少,因爲我使用更多和更多的異步方法? 例如,如果我有一個調用異步地向GetUser和內部GetUser它異步地調用GetUserHistory和內部GetUserHistory它異步地調用GetLoginData將採取行動「浪費」 4名工人,可能有服務請求的異步操作?

  3. 如果以上所有內容都是真實的,將行爲標記爲異步並使項目中的所有方法同步方法並在行動結束時(或開始時)都不可擴展 - 只是等待Task.Delay(0)所以我會「浪費」只有一名工人?

我看到的問題,我認爲有一些基本的東西我不明白。

+1

你會發現我的[異步ASP.NET的文章(https://msdn.microsoft.com/en- us/magazine/dn802603.aspx)很有幫助。 – 2015-04-01 19:13:20

+0

@StephenCleary,偉大的文章!這真的有助於我清除一些迷霧 – beautifulcoder 2015-04-01 19:32:55

+0

其次,@StephenCleary,這是我正在尋找的答案! – 2015-04-01 20:13:36

回答

2

1.As予理解的是,IIS分配X線程給每個進程...

它可以比更精細。有機器設置,IIS設置,應用程序池/域設置。

試圖瞭解線程的作用使得理解正在發生的事情非常困難。請考慮每個請求。每個請求至少使用一個線程。在異步控制器方法中,如果運行時確定存在線程上下文切換的有效機會(例如等待IO操作),則請求的繼續可能被另一個線程串聯。

因此,當請求A進來時,線程A開始履行請求。如果線程A調用IO異步操作,例如ExecuteReaderAync),則存在一個機器狀態,用於跟蹤該異步操作發生時該線程正在執行的操作。線程A變得清晰,開始完成另一個請求(B)。當機器狀態(或其它情況)確定需要線程來繼續請求(A)時,線程A或其他線程佔用機器狀態並繼續請求。

當我使用越來越多的異步方法時,可處理請求的工作量會減少嗎?

在正常情況下,不,您實際上釋放線程,通常會等待IO操作完成以處理其他請求。向方法添加異步並不會更改該方法的線程模型,它僅表示運行時可能會遇到「暫停」當前操作的機會。

3,如果上述所有屬實......

它不是,那麼斷言沒有關係。

爲什麼異步方法會調用其他線程來處理請求?

一個async方法不改變線程是如何工作的,只有使用await一樣。

我的意思是,只有異步方法會引發一個新的線程

不,這也是錯誤的。 asyncawait都不會在您的代碼中啓動一個新線程。

例子:

public async ActionResult MyMethod() 
{ 
    await DoIt(); 

    return View(); 
} 

public async void Doit() 
{ 
    await DoMore(); 
} 

public async void DoMore() 
{ 
    await Task.Delay(1000); 
} 

該代碼將只始終使用一個線程。我們不是產卵/使用額外的線程(可能來自線程池),我們正在使用機器狀態釋放線程DoMore()以滿足其他請求。同一個線程可能會也可能不會啓動並完成此請求。

更新

想你可以設置你的.NET應用程序只有每使用一個單獨的線程。請求1啓動並等待20秒以完成請求時,如果沒有異步,請求2將等待一個線程變爲可用(或獲得500個IIS線程餓死)。

ASP.Net MVC Sync

現在不是,您配置的控制器和方法,使異步調用下降到await SomeSqlAyncMethod(),線程可以自由地響應要求2和返回的HTML。一旦SQL調用完成後,該線程然後重複使用,以完成要求1

ASP.Net MVC Async

+0

感謝@Eric,你寫的例子,真的爲我清理了一些東西,如果我正確地理解了你,沒有涉及到工作者,每次調用異步方法時都只有線程切換地點。那麼可擴展性在哪裏?如果x個線程正在處理我的應用程序,那麼哪一個可以自由地完成請求或其他問題,這有什麼關係? 從你所說的話來看,我所說的關於將異步方法調用保持爲最小值,以便潛在地使用較少的線程並保持儘可能多的自由來服務請求,這有一點意義嗎? – 2015-04-01 19:10:32

+0

'如果一個線程在ExecuteReaderAync()'被阻塞,因爲它正在運行一個30秒的查詢,那麼這個線程在什麼時候什麼也不做,從SQL服務器的結果等待,'哪裏是可伸縮性'。這是不可擴展的。相反,當同樣的方法被稱爲具有await的異步時,該線程現在可以自由地執行App Pool/Domain中所需的任何操作。您利用異步調用的次數越多,可以有更多的線程可以自由地爲其他請求提供服務。這在相同的硬件/軟件上具有更高的可擴展性。 – 2015-04-01 20:33:03

+0

新增了我的技巧,在用於視覺的MsPaint中創建流程圖。 – 2015-04-01 20:50:27