2012-03-28 229 views
6

我有一個ASP.NET MVC3應用程序處理耗時的進程(從網絡複製大文件)。我們想要做的是:處理ASP.NET MVC中的異步請求

  1. 用戶點擊一個按鈕來發布形式觸發過程
  2. 應用程序啓動一個新線程開始複製文件
  3. 應用程序顯示一個消息,說該文件複製進程已經開始
  4. 用戶可以在複製處理完畢並關閉瀏覽器的同時在後臺完成。

這個想法是,用戶不需要對進程的進度進行任何確認,也不需要在進程完成時得到通知。

我們當前讓控制器在Windows服務中觸發事件,並使用Windows服務來完成實際工作。我想知道是否有更好的/更清潔的方法來做到這一點?

+3

對於MVC 3,看我的MSDN文章:http://msdn.microsoft.com/en-us/library/ee728598(VS.98).aspx如果你可以使用MVC 4和Developer Express公司11,我編寫一個簡單得多的新的Async/MVC教程。 – RickAndMSFT 2012-03-28 17:34:53

回答

6

您可以使用System.Threading.Tasks.Task調用StartNew方法與Action delegate

使用這些工具,你的控制器會是這個樣子:

[HttpPost] 
public ActionResult DoSomethingLongRunning() 
{ 
    if (ModelState.IsValid) 
    { 
     Task.Factory.StartNew(() => 
        fileCopier.CopyFile(CopyFileParameter1, CopyFileParameter2)); 

     return RedirectToAction("View Indicating Long Running Progress"); 
    } 
    else 
    { 
     // there is something wrong with the Post, handle it 
     return View("Post fallback view"); 
    } 
} 

另一種選擇是,你可以使用System.Reactive.ConcurrencyIScheduler接口TaskPoolScheduler爲具體落實執行動作(控制器構造可能注入。

public ActionResult DoSomethingLongRunning() 
{ 
    if (ModelState.IsValid) 
    { 
     ISchedulerImplementation.Schedule(new Action(() => 
     { 
      fileCopier.CopyFile(CopyFileParameter1, CopyFileParameter2); 
     })); 
     return RedirectToAction("View Indicating Long Running Progress"); 
    } 
    else 
    { 
     // there is something wrong with the Post, handle it 
     return View("Post fallback view"); 
    } 
} 

作爲一個好處,如果你做這種方式,您可以使用TestScheduler當你在單元測試接口的實現。

+0

這可能是一種選擇,但在這種情況下它不是最好的解決方案。由於用戶不需要通知觸發進程的完成情況,因此即使Web服務器出現故障,也可以在Windows服務中完全隔離,以確保其可以正常工作。 – 2012-03-28 09:32:55

3

我認爲擁有Windows服務主機您的長期運行過程是最好的選擇。如果它是由IIS託管的,那麼您總是冒着應用程序池的運行時間處於不活動狀態而死亡的風險。

一種相關的可能性是在Windows服務中託管WCF服務,併爲服務提供外部HTTP或其他端點。這樣,您的Web界面就可以調用WCF服務的「開始」合同方法,並且可能需要其他方法。

+0

良好的響應,在IIS下託管所有東西(甚至在不同的應用程序池下)創建並不會隔離您的進程,也不會使其獨立。如果IIS停止,一切都會停止。另請參閱此鏈接,瞭解IIS與Windows服務之間的區別:http://social.msdn.microsoft.com/Forums/en/wcf/thread/015d711d-ce5a-46a1-a93e-1c68746e76d3 – 2012-03-28 09:28:48

2

我將向IIS 7 WAS中託管的WCF MSMQ服務發佈請求。有an awesome article如何設置。

使用外部資源的長時間運行任務具有很高的失敗風險。開發人員經常犯的最大錯誤是假設硬件和網絡具有無限容量並且非常可靠。它通常不是。

如果長時間運行的進程被網絡連接暫時丟失或遠程服務器重新啓動而中斷,則可能會有問題甚至是災難性的。如果您的長時間運行的進程包含額外的處理,如解壓縮文件或分析文件,那麼如果沒有足夠的內存來執行處理,則可能會出現進一步的失敗風險。用戶可能提交太多的請求,並且沒有足夠的資源來處理併發問題。如果讓ASP.NET MVC應用程序通過async controllers執行處理,那麼當IIS重新啓動工作進程時,如果長時間運行的進程中斷,您可能會感到驚訝。

MSMQ 4在減輕這些風險方面做得很好。如果該過程失敗,則可以在放棄之前重試幾次。你可以學習如何設置here。您可以使用application specific deadletter queues來處理在多次可接受嘗試後進程失敗的情況。這對於業務人員診斷問題非常重要。您也可以使用此方案通過電子郵件通知用戶該進程失敗(或成功),即使請求源自的機器已關閉。

託管它在IIS而不是Windows服務提供了額外的功能。例如,如果IIS工作進程死鎖或超過內存閾值,它可以被回收。當你使用一些本地代碼來執行處理時,後者可能是一個問題。您可以每四(回答您的時間表)時間回收它。後者在處理大量管理內存時非常重要,因爲隨着時間的推移,大型對象頭部會變得非常分散,以至於幾乎不可能爲其他大型請求分配足夠的內存。您可能會發現託管在Windows服務中的WCF服務可能會遇到此問題。

實際上,這取決於您希望後臺進程的可靠程度。如果沒有,使用WCF,MSMQ和IIS可能只是矯枉過正。