我在一個 ASP.NET 專案中找到了這個(簡化的)操作方法:
[Route("")]
public async Task<HttpResponseMessage> Get()
{
// other await calls here...
StartReportGenerationInBackground();
return CreateReportRedirectResponse();
}
private void StartReportGenerationInBackground()
{
// GENERATE Report in background worker
new Task(async () => // concern with this new thread is that IIS could kill the process given the response will have already been returned.
{
var fileResult = await GetReportBytesAsync();
}).Start();
}
private async Task<FileResult> GetReportBytesAsync()
{
return await Task.Run(() => GetReportBytes());
}
private FileResult GetReportBytes()
{
// lots of CPU bound work here
}
private HttpResponseMessage CreateReportRedirectResponse()
{
var redirectResponse = Request.CreateResponse(HttpStatusCode.Moved);
redirectResponse.Headers.Location = new Uri("<reportLocationHere>");
return redirectResponse;
}
我假設呼叫StartReportGenerationInBackground()立即回傳,回應回傳給客戶端。
被啟動運行的執行緒會發生什么GetReportBytes()?
即使回應已經發送回客戶端,它是否仍然在后臺運行?
uj5u.com熱心網友回復:
new Task(...).Start();是一種不必要的復雜表達方式_ = Task.Run(...);
我假設對 StartReportGenerationInBackground() 的呼叫立即回傳,并將回應回傳給客戶端。
是的。這是一種“即發即棄”的形式,嘗試從 HTTP 請求中提前回傳的解決方案。
為運行 GetReportBytes() 而啟動的執行緒會發生什么情況?
即使回應已經發送回客戶端,它是否仍然在后臺運行?
// 這個新執行緒的問題是 IIS 可能會在回應已經回傳的情況下終止行程。
嗯,這是棘手的部分。代碼將繼續在后臺運行。直到沒有。
ASP.NET(或 IIS)中沒有任何東西會在回應回傳后立即終止此代碼,因此允許代碼繼續運行。但與此同時,ASP.NET(或 IIS)中沒有任何東西可以讓它一直運行直到完成。
更具體地說,此應用程式不允許關閉。如果應用程式停止,這種后臺作業將被丟棄(甚至沒有日志訊息通知您它發生了)。停止會定期發生:部署新版本時、縮減規模時、補丁之夜后重新啟動時、IIS 決定定期重新啟動時……而這些只是優雅的重新啟動;還有粗魯的重啟,例如硬體故障、藍屏和頂級應用程式例外。
底線是,如果這個應用程式因任何原因重新啟動,所有像這樣的后臺作業都將丟失。出于這個原因,我會說這段代碼很危險,不應該使用。
有一些適當的解決方案確實允許從 HTTP 請求中提前回傳,最值得注意的是我在博客中描述的基本分布式架構。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/513497.html
