繁体   English   中英

UI 被异步等待方法阻塞

[英]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();
}

GetVehiclesAsyncGetVehicleListAsync本质上是同步的,应该这样实现。

您的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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM