我無法理解在 REST API 中使用 async/await 的優勢。我有這個 CPU 密集型任務:
[HttpGet("GetHeavyStuffAsync")]
public async Task<string> GetHeavyStuffAsync()
{
Guid id = Guid.NewGuid();
System.Diagnostics.Debug.WriteLine($"{id} has started");
await _expensiveOperations.DoHeavyStuffOnDifferentThread();
System.Diagnostics.Debug.WriteLine($"{id} has finished");
return "request processed";
}
這是在哪里DoHeavyStuffOnDifferentThread():
public async Task DoHeavyStuffOnDifferentThread()
{
var t = Task.Run(() =>
{
var limit = 4000;
var array = Enumerable.Range(0, limit).ToArray();
stoogesort(array, 0, array.Count() - 1);
});
await t;
}
我正在使用Task.Run(() => ...以便 CPU 繁重的東西在不同的威脅中執行而不會阻塞主要的威脅,并使用 async/await 以希望控制器執行緒不會被繁重的任務阻塞并且可以繼續處理請求。
為了測驗我撰寫了一個針對 250 發起請求的程式GetHeavyStuffAsync(),然后從 swagger 我向同一個 API 控制器中的不同端點發出請求:
[HttpGet]
public IEnumerable<WeatherForecast> Get()
{
System.Diagnostics.Debug.WriteLine("GETTING FORECAST ...");
var rng = new Random();
return Enumerable.Range(1, 5).Select(index => new WeatherForecast
{
Date = DateTime.Now.AddDays(index),
TemperatureC = rng.Next(-20, 55),
Summary = Summaries[rng.Next(Summaries.Length)]
})
.ToArray();
}
如您所見,最后一個端點是 Visual Studio 在您創建 API 專案時默認創建的一個示例,它是一個非常簡單的函式,可以立即回傳。
我期望發生的事情:呼叫GetHeavyStuffAsync將被處理,await _expensiveOperations.DoHeavyStuffOnDifferentThread();控制將傳遞給執行繁重作業的執行緒,API控制器將可以自由處理另一個請求,在某個時候DoHeavyStuffOnDifferentThread將完成并且控制器將繼續該指令System.Diagnostics.Debug.WriteLine($"{id} has finished");完成該方法,可以自由繼續處理其他請求。
實際發生的是public IEnumerable<WeatherForecast> Get()需要幾分鐘才能回傳。
那么,如果我沒有使用不同的執行緒或異步/等待,為什么我的行為與我的行為沒有區別?
(注意:在測驗期間我的筆記本電腦中的 CPU 和記憶體剩余在 50% 左右)
uj5u.com熱心網友回復:
我正在使用 Task.Run(() => ... 以便 cpu 重的東西以不同的威脅執行而不阻塞主要的
在 ASP.NET 中這樣做沒有任何好處。
在桌面應用程式中,UI 只能由主執行緒更新。因此,將 CPU 密集型任務卸載到另一個執行緒是有意義的,因為它可以釋放 UI 執行緒以繼續回應用戶輸入。
但是,在 ASP.NET 中,沒有一個“主執行緒”。每個新請求都被分配一個新執行緒,直到達到最大 ThreadPool 計數,然后任何進一步的請求都必須等待。
因此,當您使用 時Task.Run,您正在釋放主請求的執行緒,但您正在使用另一個執行緒。所以對 ThreadPool 計數的凈影響仍然是相同的。
在文章ASP.NET Core Performance Best Practices中,微軟建議:
不要:
- 呼叫 Task.Run 并立即等待它。ASP.NET Core 已經在普通執行緒池執行緒上運行應用程式代碼,因此呼叫 Task.Run 只會導致額外的不必要的執行緒池調度。即使計劃的代碼會阻塞執行緒,Task.Run 也不會阻止它。
異步代碼僅在發出 I/O 請求(網路、檔案系統等)時為您提供幫助,因為在等待時確實無事可做。但是對于 CPU 密集型任務,沒有任何好處。
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/413259.html
標籤:
上一篇:呼叫句柄/鉤子的3D字串陣列
