Entity framework 在需要阻塞时如何避免异步/等待死锁

Entity framework 在需要阻塞时如何避免异步/等待死锁,entity-framework,Entity Framework,我有以下问题,来自EF的SingleOrDefaultAsync没有完成 我向a和b添加了两个额外的调用,这两个调用都返回正确的值。但是,测试行永远不会完成,方法只是永远等待 任何人都经历过类似的事情,或者对导致这种情况的原因有一些提示 public async Task<Subscription> FindSubscriptionByIdAsync(Guid subscriptionId) { //Works

我有以下问题,来自EF的SingleOrDefaultAsync没有完成

我向
a
b
添加了两个额外的调用,这两个调用都返回正确的值。但是,
测试
行永远不会完成,方法只是永远等待

任何人都经历过类似的事情,或者对导致这种情况的原因有一些提示

        public async Task<Subscription> FindSubscriptionByIdAsync(Guid subscriptionId)
        {
            //Works
            var a = DbContext.Subscriptions.SingleOrDefault(x => x.Id == subscriptionId);
            //Works
            var b = DbContext.Subscriptions.Include(s => s.StorageLocations).SingleOrDefault(x => x.Id == subscriptionId);

            //No exceptions or anyhting, it just do not continue from this 
            var test =await DbContext.Subscriptions
                .Include(s => s.StorageLocations)
                .SingleOrDefaultAsync(x => x.Id == subscriptionId);
            //Debugger never gets to this point.
            return test;

        }
我的问题是,上面实现GetStorageAccount是因为有这样一个接口,它不是返回任务的选项

因为我拥有这个接口,所以我已经更新了我的接口以返回任务,但是如果我不能更新我的设计并被迫返回对象的无任务版本,该怎么办?
执行GetStorageAccountAsync()而不执行死锁的正确方法是什么?

我发现,如果不强制它返回到相同的上下文,它就会工作

    public async Task<Subscription> FindSubscriptionByIdAsync(Guid subscriptionId)
    {

        return await DbContext.Subscriptions
            .Include(s => s.StorageLocations)
            .SingleOrDefaultAsync(x => x.Id == subscriptionId)
            .NotOnCapturedContext();

    }
公共异步任务FindSubscriptionByIdAsync(Guid subscriptionId)
{
return wait DbContext.Subscriptions
.包括(s=>s.StorageLocations)
.SingleOrDefaultAsync(x=>x.Id==subscriptionId)
.notnCapturedContext();
}
NotnCapturedContext是以下扩展方法

namespace System.Threading.Tasks
{
    using System.Runtime.CompilerServices;

    public static class TaskExtensions
    {
        public static ConfiguredTaskAwaitable NotOnCapturedContext(this Task task)
        {
            return task.ConfigureAwait(false);
        }

        public static ConfiguredTaskAwaitable<T> NotOnCapturedContext<T>(this Task<T> task)
        {
            return task.ConfigureAwait(false);
        }
    }
}
namespace System.Threading.Tasks
{
使用System.Runtime.CompilerServices;
公共静态类任务扩展
{
公共静态配置的taskawaitable notincapturedcontext(此任务)
{
返回任务。配置等待(false);
}
公共静态配置的taskawaitable notincapturedcontext(此任务)
{
返回任务。配置等待(false);
}
}
}
您一直在某处调用Wait或Result。不要那样做

如果您必须以安全的方式阻止(您已经指出)阻止:
Task.Run(anything.Result)
。不要修改您等待的所有站点。如果你错过了一个,你就会陷入僵局(可能是在晚上4点的生产中不确定)

在您的示例中,代码是:

Task.Run(() => GetStorageAccountAsync(new Guid(tenant), purpose)).Result

哪个是安全的。

你怎么知道
a
b
正在工作?您从不等待这些调用完成。使用调试器,我可以检查它们是否返回预期值。使用调试器不是一回事:当您查看值时(对于计算机),会有一个显著的延迟。您知道a和b不是任务吗?哦,:-)很明显,我的咖啡因摄入不足。这消除了问题,但这是症状的修复,而不是根本问题的修复。你会一次又一次地关注这个问题。谢谢你提醒我。情况是,在其他地方,我无法等待执行,必须使用GetAwaiter().GetResult(),现在我知道,在这些情况下,我需要先使用configureAwait以确保死锁不会发生。如果不在标准同步上下文下进行阻止,则可以在ASP.NET中安全地进行阻止<代码>任务。运行(任何操作)。结果总是安全的。不要修改您等待的所有站点。修改你屏蔽的几个站点。我理解你所说的,并更新了我的设计以反映这一点。还有一小部分我不明白,我已经用这个问题更新了这个问题。如果我专注于返回任务结果,不想执行死锁,该怎么办?如果问题中不清楚我在问什么,请告诉我。我已更新了我的答案。请注意,通过阻止这种方式,您可以抵消async在Task.Run调用的整个调用子树中带来的好处。由于ASP.NET中的好处通常为零,因此这可能不是问题。谢谢。这很有可能是我的根本问题。我只是想向其他人澄清一下(因为我第一次不得不考虑以下表达“不要修改所有等待的站点”。)不要在所有等待呼叫上配置等待(false)。对吗?对。如果出于效率原因或因为您正在开发库而希望使用ConfigureWait,则可以,。但不要在任何地方都这样做以避免僵局。你们不能错过任何一个点,否则应用程序就会在生产中遭遇灾难性的失败。我同意。无论如何,谢谢你指出这些事情。我更新了主题以反映真实问题和答案。
Task.Run(() => GetStorageAccountAsync(new Guid(tenant), purpose)).Result