2014-03-28 40 views
0

有沒有一種有效的方式來下載文件並以「背景」方式將其保存在磁盤上,而不會阻止當前在mvc控制器中執行的動作?在同步的asp.net控制器中使用Task.Run

目前,我有下面的示例代碼的工作:

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個請求)還是可靠的,或者是否有任何適當的方式來實現它?

由於

+0

使用隊列來處理任務只是爲了安全 – Ramie

回答

2

而無需在MVC控制器阻斷作用的當前執行?

答案完全取決於你的意思。

如果你的意思是讓你構建模型,而下載過程中,那麼你就可以做到這一點,而只是因爲這樣:

public ActionResult Index() 
{ 
    var task = DownloadAndSaveFileAsync(); 
    var model = GetModel(); 
    await task; 
    return View(model); 
} 

然而,如果你的意思是你想返回的響應客戶端沒有等待下載,那就更加複雜了。 I have a blog post that goes into more detail on the subject.如果您確實想在工作完成之前回復回復,那麼您需要確定該工作對您來說有多重要。

如果您需要下載,那麼您需要將下載請求放入可靠的隊列(例如,Azure隊列或MSMQ),並擁有一個獨立的後端(例如Azure工作者角色或Win32服務)實際下載和保存。

如果有下載完成它不是那麼重要 - 即,您的系統可以處理偶爾丟失下載 - 那麼你可以從我的博客文章使用BackgroundTaskManager型以上:

private void InitiateDownload() 
{ 
    BackgroundTaskManager.Run(() => DownloadAndSaveFileAsync()); 
} 

我也建議你在AppDomain在下載完成之前關閉時(例如,將消息寫入事件日誌),使用BackgroundTaskManager.Shutdown取消令牌進行適當響應。


無論您選擇哪種解決方案,您應該改變DownloadAndSaveFileAsync打開異步訪問文件流。這是文件流的常見錯誤;默認情況下它們是同步的。

+0

謝謝斯蒂芬我將使用BackgroundTaskManager。如果任務失敗,則無需擔心。 「爲異步訪問打開文件流」是否在「新的FileStream(...)」中添加useAsync:true參數? – Vindberg

+0

是的,'useAsync'會打開文件進行異步訪問。 –

+0

@StephenCleary在哪裏可以找到BackgroundTaskManager的命名空間? – GibboK

相關問題