2016-07-24 85 views
8

我使用asp.net的Web API 2和Entity Framework 6異步調用伺機長

原僞代碼

public IHttpActionResult GetProductLabel(int productId) 
{ 
     var productDetails = repository.GetProductDetails(productId); 
     var label = labelCalculator.Render(productDetails); 
     return Ok(label); 
} 

修改後的代碼

public async Task<IHttpActionResult> GetProductLabel(int productId) 
{ 
     var productDetails = await repository.GetProductDetailsAsync(productId); // 1 long second as this call goes into sub services 
     var label = labelCalculator.Render(productDetails); // 1.5 seconds synchrounous code 
     return Ok(label); 
} 
運行的同步和異步方法

在我改變之前,一切都同步運行。

我更改後,調用遠程服務,再次調用數據庫是異步等待的方式。

然後我會對只提供同步方法的渲染庫進行同步調用。計算需要1.5秒。

是否還有一個好處,我做了遠程database_service調用異步等待的方式,但第二個電話不是?還有什麼我還能改進嗎?

注意

我之所以問這個是因爲:

「隨着異步控制器時,一個進程正在等待I/O完成,它的線程被釋放了服務器用於處理其他請求。「

因此,當第一個遠程database_service調用正在處理並等待那1秒時,線程返回到IIS?

但是第二次標籤計算需要1.5秒,這會再次阻塞當前線程1.5秒?

因此,我釋放並阻止線程,這是沒有道理或你有什麼想法?

+0

當你有'async'時,你不使用'Task.FromResult',只是'return label;'你的意思是不在你的第一個例子中使用async/await嗎? –

+0

我知道......因此我向您介紹了「修改後的代碼」,這就是您現在所建議的內容。 – Pascal

回答

2

渲染庫不是簡單地「阻塞線程」,它正在執行您的渲染工作。沒有什麼比你能做的更好的了。

+0

請同時解決我的第一個問題:「是否還有一個好處,我做了遠程database_service調用異步等待的方式,但第二個調用不是?」謝謝:-) – Pascal

+0

您在這兩個示例中都調用遠程方法異步等待方式。我在評論中提出了這個問題。你的第一個代碼甚至不會編譯,所以我不能說它將如何比較,因爲第一個代碼無法運行。 –

+0

因此我寫了「pseude code」,所以無法編譯。是的,我不是故意等待我的第一個樣本。這是一個複製/粘貼錯字。我現在糾正了它。 – Pascal

1

異步代碼在底層創建了一定的延續,它是使異步編程感覺更親切的一種合成糖。

通常,根據操作本身的不同,它可以幫助使長期運行的任務同步。它將爲每個不同的長時間運行任務使用不同的任務,並以異步方式運行它們。

目前,這些任務在GetProductLabel中完全同步運行,這意味着如果它是您調用的唯一方法,則不會告訴同調代碼之間的差異。

如果有可能我會做第二個方法異步,因爲我不熟悉任何使用任務和異步等待的重大缺陷。

在你的情況下,沒有什麼比你能做的更好的了,因爲你必須同步運行它,因爲你使用的是第一種方法的結果。

1

還有一個好處,我做遠程database_service調用 異步等待的方式,但第二個電話不是?

是的,這個調用現在是非阻塞的,可以和其他代碼一起運行,即使它只有1秒鐘。

我還有什麼可以改進的嗎?

如果你可以讓第二個調用異步運行,那麼整個方法可以異步運行,並且根本不會阻塞。

+0

現在的非阻塞調用會在1秒內將線程返回給調用者,以便IIS可以在此線程上放置另一個http請求?或者,只有當方法調用異步等待時,線程纔會返回給調用方? – Pascal

+0

它會返回1秒鐘的線程。這樣想:*所有*非異步語句阻塞當前線程 - 甚至像'var s =「Hello,World」。「 - 它發生得太快無所謂。許多異步方法都有類似的聲明,但這並不能阻止他們利用異步的好處。你的第二個阻塞調用的行爲相同 - 它不會阻止異步工作的其他異步調用,它只需要很長時間。 –