ASP.NET MVC:尽管任务已完成,为什么 await 关键字会阻止我的方法?

ASP.NET MVC: Why is the await keyword blocking my method despite having the task completed?

我们有一个 ASP.NET MVC 应用程序,它有一个表单供访问者订阅他们的时事通讯的详细信息。

负责订阅用户的方法定义如下。我们还有一个自定义网站 API,我们正在通过此方法进行联系。

public async Task<string> Subscribe(User user)
{
    if (user== null) throw new ArgumentNullException("user");
    var request = new RestRequest("subscribe", Method.POST) 
    {
        RequestFormat = DataFormat.Json
    };
    request.AddBody(user);

    // Service Url is defined further up the code.
    var client = new RestClient(serviceUrl);
    var response = await client.ExecuteTaskAsync<User>(request);

    return response.Data.Id;
}

代码本身的工作原理是 returns 来自请求的适当 ID,我已经确认了这一点。问题是在网站上它仍在加载,就好像我们的时事通讯中的提交按钮仍在处理中一样。

我偷偷怀疑 await 仍在等待,因此尚未完成它 运行 但令我困惑的是,结果如何返回到我们的 CMS 中,但网站仍在加载。

有人知道吗?

Await 不会阻止您的方法,但是直到您从远程服务器获得结果(即直到任务完成),操作才会完成。 await 的目的是在等待 I/O 个操作时释放 CPU 个线程。

因此,当您等待处理您请求的线程时,可以自由处理其他请求。 await 是后端优化,对于 UI 客户端没有任何变化。

我在 UI 中的联系表似乎卡住的原因是因为在不使用 async/await 关键字的方法中调用了订阅方法。

public string Test(User user)
{
    if (user == null) throw new ArgumentNullException("user");
    Subscribe(user);

    // Rest of the method...
}

等待等待订阅任务完成并继续。当方法继续时,它将在上下文中执行。

正如本文所述post here:

In the first case, this context is a UI context (which applies to any UI except Console applications). In the second case, this context is an ASP.NET request context.

One other important point: an ASP.NET request context is not tied to a specific thread (like the UI context is), but it does only allow one thread in at a time. This interesting aspect is not officially documented anywhere AFAIK, but it is mentioned in my MSDN article about SynchronizationContext.

因此本实例中的Test方法使用了RequestContext,调用了Subscribe方法。 await 在 UI 上下文中开始,在等待时它继续返回 RequestContext,它无法访问,因为 Test 方法当前正在使用它。它以僵局告终。这就是 UI 卡在加载中的原因。