【问题标题】:Asp.net MVC5 async action result executed, but response not sent till web server shutdownAsp.net MVC5 异步操作结果已执行,但直到 Web 服务器关闭才发送响应
【发布时间】:2013-12-07 20:20:06
【问题描述】:

我有一个异步操作,它应该在等待某些任务后向浏览器返回一条 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 });
        }
    }

【问题讨论】:

  • 如果Task.Delay 有效而SeverConnectionKeeper.UpdateStation 无效,那么UpdateStation 的某处可能存在问题。确保您已在 web.config 中将 targetFramework 设置为 4.5,并且您设置了 AllowAsyncDuringSyncStages
  • @StephenCleary 我检查了targetFramework,它是4.5。我已经进入SeverConnectionKeeper.UpdateStation,并没有发现任何异常。并且最后的JsonResult一直被执行。
  • 你设置了AllowAsyncDuringSyncStages 吗?
  • HttpContext.Current.AllowAsyncDuringSyncStagesfalse。我认为我的代码中没有触及这个属性。
  • 尝试将HttpContext.AllowAsyncDuringSyncStages设置为true,结果还是一样。

标签: async-await iis-express asp.net-mvc-5 c#-5.0


【解决方案1】:

原来我调用了一个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);
    }

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-10-10
    • 2019-02-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多