c# - UI 被异步等待方法阻塞
问题描述
我DataGrid
在窗口上有 2 ,当您单击顶部的一行时,DataGrid
它会调用 CurrentChanged 事件以获取底部的数据DataGrid
以显示该汽车品牌的模型。单击一行时 UI 会被阻止,因为该方法需要一段时间才能完成。如何让异步等待工作,以免 UI 被阻塞?
public class MainWindowViewModel
{
private ObservableCollection<Company> carCollectionOC = new ObservableCollection<Company>();
private ObservableCollection<Vehicle> vehicleOC = new ObservableCollection<Vehicle>();
private VehicleService vehicleService;
public ICollectionView CarCollection { get; set; }
public ICollectionView VehicleCollection { get; set; }
public MainWindowViewModel()
{
this.carCollectionOC.Add(new Company() { Brand = "Ford", Established = 1903 });
this.carCollectionOC.Add(new Company() { Brand = "Vauxhall", Established = 1857 });
this.CarCollection = new ListCollectionView(this.carCollectionOC);
this.CarCollection.CurrentChanged += CarCollection_CurrentChanged;
this.vehicleService = new VehicleService();
this.VehicleCollection = new ListCollectionView(this.vehicleOC);
}
private async void CarCollection_CurrentChanged(object sender, EventArgs e)
{
Company company = (Company)(sender as ICollectionView).CurrentItem;
this.vehicleOC = await this.GetVehiclesAsync(company.Brand);
}
private async Task<ObservableCollection<Vehicle>> GetVehiclesAsync(string carBrand)
{
this.vehicleOC.Clear();
foreach (var item in await this.vehicleService.GetVehicleListAsync(carBrand))
this.vehicleOC.Add(item);
Console.WriteLine("finishing GetVehiclesAsync");
return this.vehicleOC;
}
}
GetVehicleListAsync 是:
public Task<List<Vehicle>> GetVehicleListAsync(string carBrand)
{
for (var i = 600000000; i >= 0; i--)
{
// simulate a long process
}
return Task.FromResult(this.vehicleList.Where(item => item.Brand == carBrand).ToList());
}
解决方案
GetVehicleListAsync
不是异步方法;它是一个同步方法,返回 a并将Task<Vehicle>
阻塞。
由于您没有执行任何异步操作,即 I/O,因此您应该使用Task.Run
将昂贵的代码卸载到 ThreadPool,从而使 UI 线程畅通无阻:
private async void CarCollection_CurrentChanged(object sender, EventArgs e)
{
Company company = (Company)(sender as ICollectionView).CurrentItem;
this.vehicleOC.Clear();
foreach (var vehicle in await Task.Run(() => this.GetVehicles(company.Brand)))
this.vehicleOC.Add(vehicle);
}
private IEnumerable<Vehicle> GetVehicles(string carBrand)
{
return this.vehicleService.GetVehicleList(carBrand));
Console.WriteLine("finishing GetVehicles");
}
public List<Vehicle> GetVehicleList(string carBrand)
{
for (var i = 600000000; i >= 0; i--)
{
// simulate a long process
}
return this.vehicleList.Where(item => item.Brand == carBrand).ToList();
}
GetVehiclesAsync
并且GetVehicleListAsync
本质上是同步的,应该这样实现。
推荐阅读
- ios - 我可以强制或诱导 iOS 14 App Tracking Transparency 授权吗?
- c++ - 忽略预编译的头文件,我应该吗?
- react-native - React native 的 Odata v4 和 axios 请求仅在 IOS 上有错误,Android 有良好的响应
- python - 如何使用python最小化所有打开的应用程序
- javascript - 如何使用 Jquery 添加/删除按钮?
- bash - 如何检查 homebrew-core 是否是 bash 脚本中的浅克隆?
- java - Spring Boot中@requestbody大容量时出现错误
- azure - 使用 ADF 从 Azure 文件共享中的目录获取文件子集
- javascript - 在 iFrame 中将 FIXED 定位到 Mainframe
- java - 使用 If-Else 语句的菜单驱动应用程序 - Java