在任务结束之前不要从行动中返回

时间:2016-12-14 10:24:19

标签: c# asp.net-web-api async-await

我在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

2 个答案:

答案 0 :(得分: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();
    });
}

答案 1 :(得分:0)

Task.Factory.StartNew is a dangerous API,正如我在博客上解释的那样。你遇到的问题是它不理解Task.Run lambdas。 (还有其他问题)。

但是,使用await不是一个合适的解决方案。它在ASP.NET上适得其反。您应该只使用public static async Task<Task> RestartAsync() { var client = new Client("..."); if (CheckApiKey(client)) return; client.Stop(); await Task.Delay(TimeSpan.FromSeconds(5)); client.Start(); }

{{1}}