2016-12-14 24 views
1

我在ASP.NET Web API動作中有點迷失在異步任務中。我有一個動作:直到任務結束時才返回動作

[HttpPost] 
public async Task<HttpResponseMessage> Restart() 
{ 
    await AspManager.Restart(); 

    return Request.CreateResponse(HttpStatusCode.OK, new { result = "Success", message = "IIS site successfully restarted" }); 
} 

重新啓動可能會長時間運行,我想等待它,然後返回響應。下面是長期運行的代碼:

public static async Task<Task> Restart() 
{ 
    var client = new Client("..."); 
    CheckApiKey(client); 

    var task = Task.Factory.StartNew(async() => 
    { 
     client.Stop(); 

     await Task.Delay(5 * 1000); 

     throw new BusinessException("test"); 
     client.Start(); 
    }); 

    return await task; 
} 

所以在主Restart方法我檢查的關鍵,那麼我應該停止服務,等待5秒鐘,並啓動服務。在這項工作完成之前,控制器的行動不應該返回。但問題是,行動返回,並在5秒後拋出BusinessException

+1

您正在任務中拋出新的異常。你爲什麼期望別的嗎? – RandomStranger

+0

嗯,那扔是爲了測試。我描述的問題是我需要等到客戶端停止並啓動,然後返回http響應。但是,它首先返回,然後才拋出異常。 –

回答

2

你的方法是async Task<Task>,你開始一個任務並返回。這意味着你正在返回一個剛剛開始的任務。

要點是:您正在等待任務創建,而不是其執行。

更改方法簽名是一個 「異步作廢」,然後從await Task.Factory.StartNew(() => versus Task.Start; await Task;,使用Task.Run()

public async Task Restart() 
{ 
    // ... 

    await Task.Run(async() => 
    { 
     client.Stop(); 

     await Task.Delay(5 * 1000); 

     client.Start(); 
    }); 
} 
+0

今天你是我的英雄:)謝謝! –

0

Task.Factory.StartNew is a dangerous API,因爲我在我的博客解釋。您遇到的問題是它不理解async lambda。 (還有其他問題)。

但是,使用Task.Run不是一個合適的解決方案。它在ASP.NET上適得其反。您應該自己使用await

public static async Task<Task> RestartAsync() 
{ 
    var client = new Client("..."); 
    if (CheckApiKey(client)) 
    return; 

    client.Stop(); 
    await Task.Delay(TimeSpan.FromSeconds(5)); 
    client.Start(); 
}