【问题标题】:async method does not continue when await statement returnsawait 语句返回时异步方法不继续
【发布时间】:2013-07-29 20:18:49
【问题描述】:

我正在使用 MVC 4,我有以下代码:

    public void DoWork(string connectionId)
    {
        connectionId = this.connectionId;
        var a =  MakeADelayAsync();
    }

    public async Task MakeADelayAsync()
    {
        await Task.Delay(5000);
        var generalHubContext = GlobalHost.ConnectionManager.GetHubContext<GeneralHub>();
        generalHubContext.Clients.Client(connectionId).showNotification("Completed");
    }

“DoWork”方法是我的 mvc 操作。我打算做的是当按下操作按钮时,“DoWork”调用异步方法并立即返回客户端。当异步方法完成他的工作时,它将使用 signalR 通知客户端。

问题出在“MakeADelayAsync”方法中,await 之后的那两行永远不会被调用。似乎等待之后流程永远不会继续。

第一个问题是“MakeADelayAsync”的问题在哪里?

第二个问题是为什么我必须编写var a = MakeADelayAsync(); 的无用代码以避免编译器警告,而我完全知道自己在做什么?反正我从不使用“a”。

【问题讨论】:

  • 尝试在线程池上启动任务。 Task.Factory.StartNew(MakeADelayAsync, TaskScheduler.Default) 之类的东西(取自记忆,可能是错误的签名)。
  • Alex,感谢您提供帮助的意图,但不,这不是答案。即使它会起作用,它也不能解释为什么 await 不会返回!
  • 之所以没有继续下去,可能是因为调度器是基于请求的,在等待完成之前请求已经结束。因此,它不会在您的延迟(或延迟本身被取消)之后调用延续。在 ThreadPool 上运行应该断开您的方法调用与请求上下文的连接。至少理论上是这样的。

标签: asp.net-mvc-4 async-await


【解决方案1】:

“DoWork”方法是我的 mvc 操作。我打算做的是当按下操作按钮时,“DoWork”调用异步方法并立即返回客户端。当异步方法完成他的工作时,它将使用 signalR 通知客户端。

这样做非常危险。我强烈建议您使用持久队列,正如我在previous answer 中所说:Azure 队列、MSMQ、WebSphere MQ 等。

但是,如果你坚持这样做很危险,那么你可以使用我博客上的代码execute background work on ASP.NET outside of a request context

public void DoWork(string connectionId)
{
    connectionId = this.connectionId;

    // This is extremely dangerous code! If ASP.NET unloads
    // your app, then MakeADelayAsync may not run to completion.
    BackgroundTaskManager.Run(() => MakeADelayAsync());
}

第一个问题是“MakeADelayAsync”的问题在哪里?

您正在执行的代码尝试在请求完成并释放请求上下文后恢复请求上下文。这是same problem you had before

第二个问题是为什么我要写 var a = MakeADelayAsync(); 的无用代码在我完全清楚自己在做什么的情况下避免编译器警告?

编译器警告告诉你代码几乎可以肯定是错误的......并且编译器是正确的。

【讨论】:

    【解决方案2】:

    您可以尝试将您的 DoWork 方法标记为 async 吗?

    public async void DoWork(string connectionId)
        {
            connectionId = this.connectionId;
            var a = MakeADelayAsync();
        }
    

    【讨论】:

    • 我无法将我的操作标记为异步,因为它会迫使我等待声明。在没有等待的情况下添加 async 没有任何意义。
    猜你喜欢
    • 1970-01-01
    • 2011-09-07
    • 1970-01-01
    • 2019-07-22
    • 2014-10-22
    • 2021-05-11
    • 1970-01-01
    • 2020-12-23
    • 1970-01-01
    相关资源
    最近更新 更多