EF6 ToListAsync冻结Winforms

时间:2014-12-20 09:17:01

标签: c# winforms entity-framework async-await

我有一个简单的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),它就可以正常工作。

有人知道我在这里失踪的是什么吗?为什么会这样?

2 个答案:

答案 0 :(得分:2)

基本上,所有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<IList<MyTableEntity>> GetMyTableAsync()
{
    using( var context = new MyEFContext() )
    {
        return await context.MyTable.ToListAsync()
             .ConfigureAwaiter(false);
    }
}

答案 1 :(得分:-1)

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

典型的意图用法是

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

但是,如果你没有别的事情要做,那么最好生成一个线程

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

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