簡體   English   中英

在同步asp.net控制器中使用Task.Run

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM