【问题标题】:EntityFramework SaveChangesAsync DeadlockEntityFramework SaveChangesAsync 死锁
【发布时间】:2014-09-08 20:04:19
【问题描述】:

我有一个具有 SaveAsync 方法的 Repository 类。

public async virtual Task<Result<int>> SaveAsync(T entity, ActionType actionType)
    {
        //some binding for return object

        try
        {
            await DbContext.SaveChangesAsync().ConfigureAwait(false);

        }
        catch (Exception e)
        {
            //logging
        }

        return retVal;
    }

以及调用 SaveAsync 方法的 MVC 控制器类:

protected override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        var entity = //getting entity
        Repository.SaveAsync(entity, ActionType.Update).GetAwaiter().GetResult();
        base.OnActionExecuted(filterContext);
    }

调试挂起在 Repository.SaveAsync(entity, ...) 行。 我已阅读 an article 关于 Task.Result 死锁问题。但是文章上的解决方案不适用于我的代码。

---更新问题

protected override void OnSaveExecuted(UserGroup entity, Result<int> operationResult, ref ActionResult actionResult)
    {
        //Execute actions if UserGroup saving operation was successfully completed
        if (!operationResult.HasError)
        {//someactions

            operationResult = Repository.SaveAsync(entity, ActionType.Update).GetAwaiter().GetResult();
        }

        base.OnSaveExecuted(entity, operationResult, ref actionResult);
    }

【问题讨论】:

  • 为什么不等待 SaveAsync?
  • @NedStoyanov OnActionExecuted 没有异步标记。 ChildActions 有同样的问题,它们不支持 async/await。
  • @phood2009,您不需要在基类中包含async 就可以将async 添加到嵌套类中被覆盖的方法中。
  • 如果您无法摆脱ref 参数,可能值得提供Save 的同步版本并调用它。这与阻塞结果相同,但没有死锁。当然,您不会获得异步的好处。
  • 您试图通过阻止任务来作弊。如果这是一件有用的事情,那么框架会自动为您阻止并且每次都这样做。

标签: c# async-await entity-framework-6


【解决方案1】:

总结一下 cmets 中讨论的内容:

  • 使用什么没有太大区别:Task.ResultGetAwaiter().GetResult() - 它们都阻塞当前线程。要摆脱死锁,您可能会一直阻塞当前线程,但您需要确保Repository.SaveAsync 中的每个异步调用都不会将其延续传递给当前线程,即。 e.有ConfigureAwait(false)
  • 最好使用await 而不是阻塞线程。在您的情况下,它需要对基类方法签名进行一些更改,因此请考虑同时实现方法的同步和异步版本。 MVC 中的异步操作不会提高应用程序的性能或响应能力(除了具有许多非 CPU 操作的高负载应用程序),因此使用同步操作就可以了。

【讨论】:

  • 感谢您提供所有信息。实际上,我在 SaveAsync 方法中使用 ConfigureAwait(false) 进行所有等待调用。但僵局仍在继续。我决定编写另一种保存方法,将使用 SaveChanges()。不是异步的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-12-27
  • 2014-06-08
  • 2013-11-30
  • 2013-12-25
  • 2015-01-29
  • 2017-03-02
相关资源
最近更新 更多