等待 DbContext 时 WPF UI 阻塞

loo*_*awa 5 c# wpf entity-framework async-await

我正在尝试异步等待,但遇到了不应该发生的 UI 阻塞。

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();

        LoadButton.Click += LoadButton_OnClick;
    }

    private async void LoadButton_OnClick(object sender, RoutedEventArgs e)
    {
        LoadButton.IsEnabled = false;

        // await Task.Delay(2000);

        using(TestContext ctx = new TestContext())
        {
            IList<User> users = await ctx.Users.ToListAsync();
        }

        LoadButton.IsEnabled = true;
    }
}
Run Code Online (Sandbox Code Playgroud)

如果我注释 DbContext 位并取消注释 Task.Delay,它会按预期运行 - 不阻塞 UI。

根据我的理解,仍然从 UI 线程调用 ToListAsync() 方法,但不应阻止它。即使该方法受 CPU 限制(可能不是),它也会导致延迟,而不是一个完整的块。

我的问题:

我理解正确吗?

为什么我的 UI 在等待 ToListAsync() 时阻塞?


编辑

我尝试在调用此方法之前进行数据库调用以预热所有内容并确保它不会阻止建立第一个连接。我还尝试向 DbSet 添加几千个条目并等待 SaveChangesAsync 并且发生了同样的事情 - UI 完全冻结了几秒钟。


编辑 2

我用相同的代码尝试了另一个例子,它似乎有效。不同之处在于,在第一个示例中,我使用的是 Code First 和 SQL CE,而在工作示例 Database First 和 SQL Server 中。

Ale*_*ese 5

SQL Server CE 中使用的连接对象不是线程安全的(未实现自然异步 API)。我相信您在使用 SQL CE 时遇到了这个问题,因为它在创建的线程上执行,DbContext并且在等待时没有将控制权返回给 UI 线程。尝试实例化DbContexta 内Task并等待结果。

LoadButton.IsEnabled = false;

var users = await Task.Run(() => 
{
    using(TestContext ctx = new TestContext())
    {
        return ctx.Users.ToList();
    }
});

LoadButton.IsEnabled = true;
Run Code Online (Sandbox Code Playgroud)