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绑定的
- 再访问Task.ConfigureAwait(continueOnCapturedContext:false)
- 在ASP.NET应用程序中执行多个线程上的方法
- VS 2010允许我在C#中使用新的async和await关键字吗?
- async / await上的MSDN示例 – 在await调用之后我不能到达断点吗?
- 我怎么在ConfiguredTaskAwaitable上“.Wait()”?
- 使用await与异步数据库调用有什么好处
- 如何使用Async / Await进行进度报告
- Task.WhenAll()和foreach(任务中的var任务)之间的区别是什么
- async / await并打开FileStream?