EntityFramework SaveChangesAsync死锁

时间:2014-09-08 10:51:05

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

我有一个具有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,...)行上挂起。 我已阅读有关Task.Result死锁问题的an article。但是文章的解决方案不适用于我的代码。

---更新问题

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);
    }

1 个答案:

答案 0 :(得分:3)

总结评论中讨论的内容:

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