我有一个包含4个gridviews的表单。由于实体框架,我想用查询的对象填充这些gridview。问题在于,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在整个过程中仍会阻塞。我在做什么错了?
答案 0 :(得分: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();
}