Asp.net MVC5异步操作结果已执行,但直到web服务器关闭后才发送响应



我有一个异步操作,它应该在等待一些任务后向浏览器返回一条JSON消息。尽管ActionResult已经成功构建并执行(我使用的是我自己的JsonResult,所以我通过进入源代码来确认这一点),但浏览器仍然没有得到任何响应(Fiddler确认了)。

同时,如果我正在等待Task.Delay(),并返回一条伪消息,它就会起作用。

奇怪的是,如果我在IIS Express运行我的网站时使用VS2013重建我的项目,浏览器会突然收到几分钟前应该发送的消息!我认为这是关闭网络服务器造成的,但我不知道这到底是怎么发生的。

我已经调试了一天,禁用了所有我认为可能相关的东西,但运气不佳。因此,任何关于这种奇怪行为的原因的帮助都是受欢迎的。谢谢,这是代码:

    [HttpPost]
    public async Task<JsonResult> Update(string token)
    {
        try
        {
            //This works
            //await Task.Delay(TimeSpan.FromSeconds(1));
            //return Json(new { error = "testing." });
            //This won't work
            var feedback = await ServerConnectionKeeper.UpdateStation(token);
            return feedback.Success
                ? Json(new { redirect = Url.Action("Index", "Home") })
                : Json(new { error = feedback.Error });
        }
        catch (Exception ex)
        {
            return Json(new { error = ex.Message });
        }
    }

原来我调用了一个async void方法,它使一些奇怪的未知(我)事情发生了。以下是一些概念代码:

    [HttpPost]
    public async Task<JsonResult> Data()
    {
        await SomeTask();
        return Json(new { message = "Testing" });
    }
    private async Task SomeTask()
    {
        FireAndForget();
        await Task.Delay(TimeSpan.FromSeconds(1)).ConfigureAwait(false);
    }
    private async void FireAndForget()
    {
        await Task.Delay(TimeSpan.FromSeconds(100)).ConfigureAwait(false);
    }

对于上面的代码,我认为在请求后1秒就会得到响应。但事实并非如此,甚至不到100秒。在某些情况下,我会得到InvalidOperationException,而在其他情况下,则一无所获。

如果我把async void改成async Task,不管是不是ConfigureAwait(false),一切都会起作用:

    [HttpPost]
    public async Task<JsonResult> Data()
    {
        await SomeTask();
        return Json(new { message = "Testing 4" });
    }
    private async Task SomeTask()
    {
        FireAndForget();
        await Task.Delay(TimeSpan.FromSeconds(1)).ConfigureAwait(false);
    }
    private async Task FireAndForget()
    {
        await Task.Delay(TimeSpan.FromSeconds(100)).ConfigureAwait(false);
    }

在我的生产代码中,当web服务器关闭时发送响应的原因是,我的FireAndForget()方法有一个async循环读取网络消息,并且在连接关闭之前从不返回,关闭web服务器会关闭连接。但我仍然觉得奇怪的是,我没有在那里拿到InvalidOperationException

最新更新