【问题标题】:Fill GridViews with Entity Framework Asynchronously用实体框架异步填充 GridView
【发布时间】:2019-11-02 04:47:20
【问题描述】:

我有一个包含 4 个网格视图的表单。由于实体框架,我想用我查询的对象填充这些网格视图。问题是 UI 在加载时卡住了。因此,我试图使查询异步,但它不起作用。我尝试了几种方法,但我目前的解决方案看起来像这样

        private async void SwiftCheck_Load(object sender, EventArgs e)
        {
            radGridViewLast7Days.DataSource = await MonitoringToolCore.SwiftQueries.ReturnLast7DaysAsync();
            radGridViewAmount.DataSource = await MonitoringToolCore.SwiftQueries.CompareAmountsAsync();
            radGridViewAmountBySwift.DataSource = await MonitoringToolCore.SwiftQueries.CompareAmountsByTypeAsync();
            radGridViewAmountBySender.DataSource = await MonitoringToolCore.SwiftQueries.CompareAmountsBySenderAsync();

            //Code to adapt the gridviews layout after data has been bound
            this.radGridViewAmountBySender.BestFitColumns();

        }

我在 load 事件中绑定数据,因为据我了解,我不能在构造函数中使用 await。 然后我在每个任务上使用 await 因为实体框架不是线程安全的。所以如果我理解正确的话,我不能同时启动每个任务然后等待它们吗?

这是返回对象列表的代码之一

        public static async Task<List<MsMessage>> ReturnLast7DaysAsync()
        {
            DateTime currentDate = DateTime.UtcNow.Date.AddDays(-7);

            using (var db = new SveulumeContext())
            {

                var query = db.MsMessages
                    .Where(u => u.Created >= currentDate);

                return await query.ToListAsync();               

            }
        }

代码正常工作并正确绑定了gridViews,但UI在整个过程中仍然阻塞。我做错了什么?

【问题讨论】:

  • @SachaDieryck:您的数据库提供商是什么?
  • @iSpain17:异步LINQ使用正确。
  • @iSpain17 我不在乎我的用户与网格交互,但应用程序执行其他操作,我不希望它在查询进行时阻塞。我尝试使用后台工作人员,但随后出现错误“控制”,该错误是从创建它的线程以外的线程访问的”。所以我想最好的解决方案是启动一个后台线程来进行查询,等待它的结果,然后在主线程中绑定数据?我想如果我这样做,我的 LINQ 查询就不再需要异步了?
  • @StephenCleary 它是一个预言机数据库

标签: c# entity-framework async-await


【解决方案1】:

根据this answer,Oracle 在其 .NET 库中不支持异步查询。因此,您执行异步 LINQ 的方式是正确的;只是Oracle不支持它。这就是您看到查询同步运行而不是异步运行的原因。

要从 UI 线程中获取代码,您可以使用 Task.Run。我还建议在代码中添加注释,因为它看起来错误:

// Task.Run is necessary because Oracle does not support async: https://stackoverflow.com/questions/29016698/can-the-oracle-managed-driver-use-async-wait-properly/29034291#29034291
radGridViewLast7Days.DataSource = await Task.Run(() => MonitoringToolCore.SwiftQueries.ReturnLast7DaysAsync());

附带说明,EF 确实支持多个同时查询如果它们每个都使用自己的数据库上下文。由于您的方法确实使用自己的数据库上下文,因此您可以同时加载所有这些查询:

private async void SwiftCheck_Load(object sender, EventArgs e)
{
  // Task.Run is necessary because Oracle does not support async: https://stackoverflow.com/questions/29016698/can-the-oracle-managed-driver-use-async-

  var last7DaysTask = Task.Run(() => MonitoringToolCore.SwiftQueries.ReturnLast7DaysAsync());
  var compareAmountsTask = Task.Run(() => MonitoringToolCore.SwiftQueries.CompareAmountsAsync());
  var compareAmountsByTypeTask = Task.Run(() => MonitoringToolCore.SwiftQueries.CompareAmountsByTypeAsync());
  var compareAmountsBySenderTask = Task.Run(() => MonitoringToolCore.SwiftQueries.CompareAmountsBySenderAsync());
  await Task.WhenAll(last7DaysTask, compareAmountsTask, compareAmountsByTypeTask, compareAmountsBySenderTask);
  radGridViewLast7Days.DataSource = await last7DaysTask;
  radGridViewAmount.DataSource = await compareAmountsTask;
  radGridViewAmountBySwift.DataSource = await compareAmountsByTypeTask;
  radGridViewAmountBySender.DataSource = await compareAmountsBySenderTask;

  //Code to adapt the gridviews layout after data has been bound
  this.radGridViewAmountBySender.BestFitColumns();
}

【讨论】:

  • 解释清楚,我刚试了代码,它可以工作,谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-09-02
  • 2015-02-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多