2013-10-02 55 views
1

假設我有一個需要相當長的時間,直到完成其工作如下異步方法:異步/等待在ASP.NET的WebAPI

void async Task LongWork() 
{ 
    await LONGWORK() // ... long work 
} 

現在,在網頁API,我想運行在後臺(即工作,我想在開始是LongWork(),但其完成之前後返回HTTP請求:

我能想到的三種方法來實現這一目標:

1) public async Task<string> WebApi() 
    { 
     ... // do another work 

     await Task.Factory.StartNew(() => LongWork()); 

     return "ok"; 
    } 
2) public async Task<string> WebApi() 
    { 
     ... // do another work 

     await Task.Factory.StartNew(async() => await LongWork()); 

     return "ok"; 
    } 

3) public async Task<string> WebApi() 
    { 
     ... // do another work 

     Task.Factory.StartNew(async() => await LongWork()); 

     return "ok"; 
    } 

Q1:方法#1和#2有什麼區別?在這個例子中,在後臺線程中包含一些async/await對的LongWork()方法是什麼? 特別是在#3中,有沒有 「等待」 Task.Factory.StartNew之前(異步()=>等待LongWork()),它是精細

感謝

回答

7

Q1:?!有什麼辦法#1和#之間的區別2?

#1的開銷較小,這是唯一的區別。

Q2:什麼是,在ASP.NET的世界,運行方法(在這個例子中,正確的方式,包含了一些異步LongWork()/等待對在後臺線程

?你提供的選項無一件事,他們都use Task.Factory.StartNew without specifying a TaskScheduler, which is dangerous(我形容我的博客),他們應該使用Task.Run來代替。但是,即使你使用Task.Run,你會遇到更嚴重的潛在問題。

底層的問題是:HTTP協議以每個請求爲中心g恰好是一個匹配的響應。當一個HTTP服務器(如ASP.NET)知道沒有未完成的請求時,它會做出如下假設:「回收工作進程是安全的」。

I describe this problem in more detail on my blog。此外,該博文中還有一個BackgroundTaskManager類型,它向ASP.NET運行時註冊後臺任務,並通過Task.Run(正確)執行它們。 如果您閱讀博文並理解並接受這仍然是危險和不安全的,那麼您應該只使用BackgroundTaskManager

一個更好的解決方案是先寫出一個表示要完成的工作(例如,Azure隊列)並擁有一個獨立的後端進程(例如Azure worker角色)處理來自隊列的請求。