【问题标题】:EF Core - Async functions are blocking UIEF Core - 异步函数阻塞 UI
【发布时间】:2021-05-26 05:50:56
【问题描述】:

也许我错了,这实际上是好的行为,但是我不明白,为什么他们甚至会将异步后缀放在方法名称中并使其可等待。

只是为了轻松重现,这就足够了:

private async void Button_Click(object sender, RoutedEventArgs e)
{
    using var ctx = new eWMSContext();
    var a = await ctx.TJobLines.ToListAsync();
}

这个调用会阻止 UI,尽管它看起来不应该,并且将其包装到 Task.Run 似乎不合逻辑。

我找不到任何资源为什么会发生这种情况。

此资源解释说,它不应该阻止 UI,但它会: https://docs.microsoft.com/lt-lt/ef/core/miscellaneous/async

我正在使用(所有都是 .NET Core 3.1 的最新版本):
EF Core 3.1.12
Oracle.EntityFrameworkCore 3.19.80
Oracle.ManagedDataAccess.Core 2.19.101

【问题讨论】:

  • ToListAsync()是其中唯一的 async 部分,并且大部分时间(和阻塞)发生在同步构造函数和属性获取器上。
  • 有些相关:Why File.ReadAllLinesAsync() blocks the UI thread?。不幸的是,现实并不总是符合我们的期望。幸运的是,我们有 Task.Run 在需要时为我们提供帮助。
  • @PoulBak 你好,它真的没有。我做了测试,阻塞部分是 ToListAsync 本身。 FindAsync、FirstOrDefaultAsync 等的相同帐户...所有 EF Core 异步方法都阻塞了 UI。
  • @TheodorZoulias 嘿,谢谢你的链接,大概就是这样......说实话有点难过。无论如何感谢这篇文章

标签: c# wpf entity-framework async-await entity-framework-core


【解决方案1】:

不幸的是,这些方法的实际实现似乎还有一些不足之处:

Why would an EF query with ToListAsync hang in a WPF application?

作为一种解决方法,为了让您的 UI 保持响应,您可以在后台线程上执行同步版本:

private async void Button_Click(object sender, RoutedEventArgs e)
{
    await Task.Run(() =>
    {
        using var ctx = new eWMSContext()
        {
            var a = ctx.TJobLines.ToList();
        }
    });
}

那么您不必依赖ToListAsync 的实现是非阻塞的。

【讨论】:

  • +1。我建议将a 变量设为Task.Run 方法的结果,因为很可能OP 想用它来更新UI 控件。从 Task.Run 内部访问 UI 控件是一个容易犯的常见错误。
  • 嗯,这很可悲。那他们为什么要实现异步功能呢?甚至像 FindAsync 一样,FirstOrDefaultAsync 块也是如此。这对我来说很伤心。我什至看不到使用异步等待的理由。
  • @TheodorZoulias 我正在使用 MVVM 和响应式 UI,单击此按钮实际上只是为了最简单地重现问题。
  • "他们为什么要实现异步函数呢?" -> 因为 ToListAsync 可以针对 any IQueryable 调用,而不管如何它被实施。您遇到了 Oracle 驱动程序的限制。使用 SQL Server 驱动程序(例如)调用 ToListAsync 不会阻塞。
猜你喜欢
  • 2016-02-15
  • 2015-04-20
  • 2016-03-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-07-07
  • 1970-01-01
相关资源
最近更新 更多