[英]UI is blocking with async await methods
我在一個窗口上有 2 個DataGrid
,當您單擊頂部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
不是異步方法; 它是一個同步方法,它返回一個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
本質上是同步的,應該這樣實現。
您的GetVehicleListAsync
方法實際上不是異步的。 將其更改為:
public Task<List<Vehicle>> GetVehicleListAsync(string carBrand)
{
return Task.Run(() =>
{
for (var i = 600000000; i >= 0; i--)
{
// simulate a long process
}
return this.vehicleList.Where(item => item.Brand == carBrand).ToList();
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.