我在ASP.NET應用程序中有一個方法,它需要花費很多時間才能完成。根據用戶提供的緩存狀態和參數,在一次用戶請求期間,對此方法的調用最多可能發生3次。每次通話大約需要1-2秒鐘才能完成。該方法本身是對服務的同步調用,並且不可能覆蓋實現。
所以給服務的同步調用看起來像下面這樣:將異步代碼包裝爲異步調用
public OutputModel Calculate(InputModel input)
{
// do some stuff
return Service.LongRunningCall(input);
}
,並且該方法的使用量(注意,方法是調用可能發生一次以上):
private void MakeRequest()
{
// a lot of other stuff: preparing requests, sending/processing other requests, etc.
var myOutput = Calculate(myInput);
// stuff again
}
我試圖從我身邊改變實現來提供這種方法的同時工作,這是我到目前爲止所做的。
public async Task<OutputModel> CalculateAsync(InputModel input)
{
return await Task.Run(() =>
{
return Calculate(input);
});
}
利用率(「做其他的東西」碼部分與呼叫服務同時運行):
private async Task MakeRequest()
{
// do some stuff
var task = CalculateAsync(myInput);
// do other stuff
var myOutput = await task;
// some more stuff
}
我的問題如下。我是否使用正確的方法來加快ASP.NET應用程序的執行速度,還是我在做不必要的工作來試圖異步運行同步代碼?任何人都可以解釋爲什麼第二種方法不是ASP.NET中的選項(如果它不是)?另外,如果這種方法適用,我是否需要異步調用這種方法,如果它是我們目前可能執行的唯一調用(我有這種情況,在等待完成時沒有其他任何東西需要執行)?
關於此主題的網絡中的大多數文章都包含使用async-await
方法的代碼,該方法已經提供了awaitable
方法,但這不是我的情況。 Here是描述我的情況的好文章,它沒有描述並行調用的情況,拒絕包裝同步調用的選項,但在我看來,我的情況恰恰是這樣做的時機。
在此先感謝您的幫助和提示。
非常感謝您的詳細解答。還有一件事我想澄清。當我使用'Task.Run'開始執行時,內容會在另一個線程中運行,這是從線程池中獲取的。然後,根本不需要將阻塞調用(例如我的調用服務)封裝到「運行」中,因爲它們總是會消耗一個線程,並在執行該方法期間被阻塞。在這種情況下,在我的情況下,'async-await'留下的唯一好處是一次執行多個操作。請糾正我,如果我錯了。 – Eadel
另外,僅僅爲了指定,「服務」是對遠程web服務的調用,它不是CPU綁定到我們的服務器,但它需要一些時間來獲得來自遠程機器的響應。關於第二個假設的話題,我們提供用戶在大多數請求期間做一些工作的選項,但在我們的情況下,速度和服務器負載都很重要。該應用程序不是內部應用程序,因此可能會有大量的請求高峯負載。 – Eadel
是的,您從'Run'(或'Parallel')獲得的唯一好處是併發性。這些操作仍然會阻塞一個線程。既然你說服務是一個Web服務,那麼我不建議使用'Run'或'Parallel';相反,爲服務編寫一個異步API。 –