2012-07-15 82 views
5

如何在控制器方法內執行異步方法並返回HttpStatusCodeResult(200),而不會異步委託過早終止其執行?如何正確執行ASP.net MVC中的異步方法?

我正在處理一個asp.net應用程序,我的一個操作是我的主控制器需要很長時間才能運行(10-30秒)。我想返回一個HttpStatusCodeResult(200)並繼續運行我的函數。該功能不需要返回任何東西,但仍然不是真正的火災和遺忘,因爲我立即用HttpStatusCodeResult將響應返回給服務器。

我嘗試使用委託,但似乎一旦我從操作返回狀態代碼,委託停止執行。另一種選擇是創建一個Windows服務,但這就像使用火箭筒殺死蒼蠅。我收到的請求很少,所以資源和性能對我來說不是問題。我聽說ThreadPool.QueueUserWorkItem是一個選項,但哪種最適合我的情況?

+0

這可能是你最好的選擇:[在ASP.NET MVC中使用異步控制器](http://msdn.microsoft.com/en-us/library/ee728598.aspx) – 2012-07-15 18:56:06

+0

但我認爲它只是優化了用法線程池,我的意思是我不能返回httpstatus代碼並繼續執行,檢查_Converting同步操作方法異步操作方法_部分 – 2012-07-15 19:04:25

回答

1

創建一個靜態類來管理這個長時間運行的操作。這個類將負責創建線程來執行任務,並提供一種方法來檢查任何正在進行的操作的狀態(即,如果它仍在進行中或已經完成,並且如果是的話,結果是什麼)。

您的MVC控制器方法然後使用這個類來完成工作並向用戶呈現狀態信息或完成的處理數據。

事情是這樣的:

public ActionResult GetSomething(String id) { 
    TaskResult result = TaskClass.GetStatus(id); 
    if(result == null) { // the task has not been run, so start it up 
     TaskClass.StartNew(id); 
     return new View("PleaseWait"); 
    } else if(!result.IsFinished) { 
     return new View("PleaseWait"); 
    } else { 
     return View("Results", result); 
    } 
} 

public static class TaskClass { 
    private static Dictionary<String,TaskResult> _tasks; 
    public static TaskResult GetStatus(String id) { 
     // TODO: Make this code thread-safe 
     if(_tasks.ContainsKey(id)) return _tasks[id]; 
     return null; 
    } 
    public static void Start(String id) { 
     _tasks.Add(id, new TaskResult("Working")); 
     Thread thread = new Thread(SomeExpensiveOperation); 
     thread.Start(id); 
    } 
} 

在SomeExpensiveOperation年底會有代碼完成這標誌着TaskResult。

+0

這聽起來像它可能工作。我無法弄清楚的唯一部分是:*一旦控制器方法執行完畢,誰仍在監聽異步結果?* – 2012-07-15 18:49:17

+0

沒有人。不需要成爲聽衆。只需將完成的操作的結果存儲在內存中,直到客戶端請求它爲止。查看我的更新答案的例子。在這種情況下,我使用一個字典(請注意,我的代碼不是線程安全的,充滿了bug,但你應該能夠得到一般的想法)。 – Dai 2012-07-15 18:52:52