【问题标题】:Preventing a deadlock when calling an async method without using await在不使用 await 的情况下调用异步方法时防止死锁
【发布时间】:2012-08-06 22:39:34
【问题描述】:

我需要调用一个从内部返回 Task 的方法

public override void OnActionExecuting(ActionExecutingContext filterContext)

它不会让我使这个方法异步它会抛出以下内容

异步模块或处理程序在异步完成时完成 操作仍在等待中。

以及调用时

 entityStorage.GetCurrentUser().Result

我遇到了僵局。我怎样才能避免这种情况?

我一直在玩弄它,想出类似的东西

entityStorage.GetCurrentUser().Result.ConfigureAwait(false).GetAwaiter().GetResult();

但这不起作用。我该怎么做?我的解决方案需要使用 ASP.NET 4 和 Async Targetting Pack,我无法像部署到 Azure 一样使用 ASP.NET 4.5。

【问题讨论】:

  • 在这里找到答案stackoverflow.com/a/5097066/168012如果有人有更好的解决方案请分享
  • 您是从AsyncController 而不是Controller 派生的吗?
  • vote here 让 MVC 团队添加对 async 操作过滤器的支持。

标签: asp.net asp.net-mvc asp.net-mvc-3 asp.net-4.0 async-await


【解决方案1】:

死锁的原因是explained here。简而言之,不要阻塞async 代码。你应该在你的库中使用ConfigureAwait(false) async 代码和await 结果(不要使用ResultWait)。

更新:vote here 让 MVC 团队添加对 async 操作过滤器的支持。

【讨论】:

  • 我很难找到这样说的链接/页面,但我过去曾让其他人告诉我,如果提供链接(尤其是 SO 外部的链接),你应该将关键位复制到 SO 答案中。不过,这里有点提到它,FWIW:meta.stackexchange.com/questions/118582/…
  • 你是对的;您所指的元问题最近作为“让我们让 SO 成为一个更好的地方”战略的一部分被删除。然而,正如 Jon Skeet 评论的那样:如果我知道答案并且只有时间发布链接,那总比没有好。
  • 我遇到的问题是,如果我尝试使用 async 关键字并使方法异步,则该方法会抛出“异步模块或处理程序已完成,而异步操作仍处于挂起状态。”
  • ASP.NET 告诉你不能在那里使用异步方法。您可以使用ContinueWith 强制它,但这会在 ASP.NET 中带来其自身的问题。
  • 好的,那么在不使用 .NET 4.5 的情况下有没有好的解决方案?我发现的唯一其他解决方案是我作为对该问题的评论提出的解决方案,实际上我最终使用了该解决方案,因为我需要在调用后存储一个 cookie,而使用 ContinueWith 时这是不可能的
【解决方案2】:

由于 await 只是编译器为您重写延续的语法糖,因此最“直接”的路径是采用将遵循您的 await 的任何代码并将其设为 ContinueWith 调用。

所以,类似:

entityStorage.GetCurrentUser().ContinueWith(t =>
{
    // do your other stuff here
});

【讨论】:

    【解决方案3】:

    如果您必须将异步转换为同步。

    public User GetCurrentUserSynch()
        {
            return Task.Run(() =>
            {
                var asyncResult = entityStorage.GetCurrentUser();
                while (!asyncResult.IsCompleted)
                {
                    Application.Current.TryFindResource(new object()); // This is for WPF but you can do some other nonsense action of your choosing
                }
    
                return asyncResult.Result;
            }).Result;
        }
    

    否则使用@Stephen 的答案。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-09
      • 2019-08-14
      • 2017-02-18
      • 2017-06-21
      相关资源
      最近更新 更多