2014-02-10 26 views
3

什麼是隻處理單異步操作正確的情況?例如,我需要導入大文件,並且在導入時我需要禁用該選項以確保不會觸發第二個導入。的Web API只允許單個異步任務

什麼來記住:

[HttpPost] 
public async Task<HttpResponseMessage> ImportConfigurationData() 
{ 
    if (HttpContext.Current.Application["ImportConfigurationDataInProcess"] as bool? ?? false) 
      return Request.CreateErrorResponse(HttpStatusCode.InternalServerError, "Task still running"); 

    HttpContext.Current.Application["ImportConfigurationDataInProcess"] = true; 

    string root = HttpContext.Current.Server.MapPath("~/App_Data"); 
    var provider = new MultipartFormDataStreamProvider(root); 
    await Request.Content.ReadAsMultipartAsync(provider); 

    //actual import 

    HttpContext.Current.Application["ImportConfigurationDataInProcess"] = false; 
    Request.CreateResponse(HttpStatusCode.OK, true) 
} 

但好像非常硬編碼解決方案。什麼是正確的處理方式? 另一件事情是不正確的在客戶端工作,它仍然等待迴應。所以有可能是用戶只要到該文件發送到服務器,而不是等待熄滅它會完成,但重裝發送到服務器上的文件後,頁面,而無需等待,同時await東西將結束。

回答

6

async does not change the HTTP protocol(我在我的博客解釋)。所以你每個請求只能得到一個響應。

適當解決方法是保存在一些可靠的存儲(例如,天青表/隊列)「令牌」(和導入數據)的工作,並有一個獨立的處理的後端來完成實際的進口。然後

ImportConfigurationData行動將檢查令牌是否已經存在的數據,如果發現故障的要求。

+0

謝謝回答。但我不打算改變協議。我希望以某種方式啓動任務,並在該任務仍在進行時調用此請求時發送一​​些錯誤響應。 – Vladimirs

+0

我理解並可以接受該解決方案帶來的風險。而且我無法爲此設置Azure。我試過Task.Factory.StartNew(async()=> //一些導入代碼);但是它在等待Request.Content.ReadAsMultipartAsync(provider)後不喜歡async();並似乎我的任務附加到主線程 – Vladimirs

+1

@Vladimirs:我的文章的一點是'異步'不會更改HTTP協議。如果您使用的是HTTP,那麼每個請求只能得到一個響應。因此,如果您想在導入完成之前將響應返回給客戶端,那麼您需要更復雜的解決方案。 Azure只是可靠存儲的一個例子;您不必使用Azure來解決此問題。 –