EF Core - 异步函数阻塞 UI
Posted
技术标签:
【中文标题】EF Core - 异步函数阻塞 UI【英文标题】:EF Core - Async functions are blocking 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。
另一个相关问题:Can the Oracle Managed Driver use async/wait properly?
@TheodorZoulias 嘿,谢谢你的链接,大概就是这样......说实话有点难过。无论如何感谢这篇文章
【参考方案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
不会阻塞。以上是关于EF Core - 异步函数阻塞 UI的主要内容,如果未能解决你的问题,请参考以下文章
UIImage initWithData:从异步调度中阻塞 UI 线程?
异步代码是不是在 UI 线程或新/不同线程中运行以不阻塞 UI?