EF6 ToListAsync冻结Winforms

我有一个简单的Winforms应用程序,上面有一个按钮。 首先使用EF 6.1.1代码,如果我在查询中使用.ToListAsync,它将冻结表单,直到结果从SQL Server返回。

private async void button1_Click(object sender, EventArgs e) { using( var context = new MyEFContext() ) { var result = await context.MyTable.ToListAsync(); MessageBox.Show(result.Count); } } 

如果我将.ToListAsync()调用放在不同的同步上下文中,可以通过在它之前添加await Task.Delay(1).ConfigureAwaiter(false)来实现它的工作原理。

有人知道我在这里缺少什么吗? 为什么会这样?

基本上,所有async代码都是同步的,直到第一个await

可能发生的是设置(打开连接等)需要花费太多时间。

你应该总是尽可能多地在UI线程之外推送。 像这样的东西:

 private async void button1_Click(object sender, EventArgs e) { this.button1.Enabled = false; var result = await GetMyTableAsync(); MessageBox.Show(result.Count); this.button1.Enabled = true; } private async Task> GetMyTableAsync() { using( var context = new MyEFContext() ) { return await context.MyTable.ToListAsync() .ConfigureAwaiter(false); } } 

查询数据库是一种IO绑定操作,因此在设计上,它在与调用代码相同的同步上下文中运行。

典型的意图用法是

 var task = context.Table.ToListAsync(); // do something else here var result = await task; 

但是,如果你没有其他任何事情要做,那么最好生成一个线程

 var result = await Task.Run>(() => context.Table.ToListAsync()); 

这意味着你的任务现在既是cpu又是io绑定的