[英]Using Task.Run in a syncronous asp.net controller
有沒有一種有效的方法來下載文件並以“后台”方式將其保存在磁盤上,而不會阻止當前在mvc控制器中執行某項操作?
目前,我正在使用以下示例代碼:
public ActionResult Index()
{
InitiateDownload();
var model = GetModel();
return View(model);
}
private void InitiateDownload()
{
Task.Run(() => DownloadAndSaveFileAsync()).ConfigureAwait(false);
}
private async Task DownloadAndSaveFileAsync()
{
var response = await GetResponse();
using (var fileStream = new FileStream("c:\\file.zip", FileMode.Create, FileAccess.Write, FileShare.None))
{
await response.Content.CopyToAsync(fileStream).ConfigureAwait(false);
}
}
public async Task<HttpResponseMessage> GetResponse()
{
var client = new HttpClient();
client.BaseAddress = new Uri("http://someUrl.com");
return await client.GetAsync("someResourceEndPoint").ConfigureAwait(false);
}
我讀過幾個地方,您不應該在服務器上(在工作線程中)使用Task.Run,所以我想知道此示例是否可擴展(例如,它每秒接收10個請求)還是可靠的,或者是否存在任何適當的方法?如何做到這一點?
謝謝
不會在MVC控制器中阻止當前執行動作?
答案完全取決於您的意思。
如果您打算在下載進行時允許您構建模型,則可以這樣簡單地進行操作:
public ActionResult Index()
{
var task = DownloadAndSaveFileAsync();
var model = GetModel();
await task;
return View(model);
}
但是,如果您要在不等待下載的情況下將響應返回給客戶端,則要復雜得多。 我有一篇博客文章,詳細介紹了該主題。 如果您確實想在完成工作之前返回響應,那么您需要確定該工作對您來說有多重要。
如果需要進行下載,則需要將下載請求放入可靠的隊列(例如,Azure隊列或MSMQ)中,並有一個獨立的后端(例如,Azure工作角色或Win32服務)來進行實際的下載和保存。
如果下載不那么重要-即您的系統可以處理偶爾丟失的下載-那么您可以使用上面我的博客文章中的BackgroundTaskManager
類型:
private void InitiateDownload()
{
BackgroundTaskManager.Run(() => DownloadAndSaveFileAsync());
}
我還建議您在下載完成之前關閉AppDomain時使用BackgroundTaskManager.Shutdown
取消令牌進行適當響應(例如,將消息寫入事件日志)。
無論選擇哪種解決方案,都應更改DownloadAndSaveFileAsync
以打開文件流以進行異步訪問。 這是文件流的常見錯誤; 默認情況下,它們是同步的。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.