Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/cmake/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在构造函数中运行async方法会停止显示数据的ObservableCollection_C#_Wpf_Async Await_Task - Fatal编程技术网

C# 在构造函数中运行async方法会停止显示数据的ObservableCollection

C# 在构造函数中运行async方法会停止显示数据的ObservableCollection,c#,wpf,async-await,task,C#,Wpf,Async Await,Task,我在构造函数中调用异步方法时遇到了一个问题。它会停止数据在可观测集合中的显示,即使我在调试中跟踪代码时可以看到它。为了解决这个问题,我有一个相同方法的非异步版本,但显然这并不理想。如何使我的异步方法在构造函数中正常工作 如果我在MainWindowViewModel的构造函数中调用this.RefreshCarList(“”),则随后调用this.RefreshCarListAsync(“”)(不是从构造函数中调用)将工作得非常好,并且数据会显示在屏幕上。如果我只调用this.RefreshCa

我在构造函数中调用异步方法时遇到了一个问题。它会停止数据在
可观测集合中的显示,即使我在调试中跟踪代码时可以看到它。为了解决这个问题,我有一个相同方法的非异步版本,但显然这并不理想。如何使我的异步方法在构造函数中正常工作

如果我在
MainWindowViewModel
的构造函数中调用
this.RefreshCarList(“”)
,则随后调用
this.RefreshCarListAsync(“”)
(不是从构造函数中调用)将工作得非常好,并且数据会显示在屏幕上。如果我只调用
this.RefreshCarListAsync(“”)
,那么数据永远不会显示

public class MainWindowViewModel
{
    private ObservableCollection<Car> carList;
    public ICollectionView CarList { get; private set; }
    private DataReceivedHandler dataReceivedHandler = new DataReceivedHandler();

    public MainWindowViewModel()
    {
        //this.RefreshCarList(""); // Gets data on startup
        this.RefreshCarListAsync("") // Doesn't show any data
        this.CarList = new QueryableCollectionView(this.carList, typeof(Car));
    }

    public void RefreshCarList(string carBrand)
    {
        this.carList = this.dataReceivedHandler.GetCarList(carBrand);
    }

    public async Task RefreshCarListAsync(string carBrand)
    {
        this.carList = await this.dataReceivedHandler.GetCarListAsync(carBrand);
    }
}

请注意,
this.carList
RefreshCarListAsync
中初始化:

this.carList = await this.dataReceivedHandler.GetCarListAsync(carBrand);
但它可能不是立即初始化,而是在
GetCarListAsync
提供结果后初始化。然后,在构造函数中,您不需要等待
RefreshCarListAsync
(无论如何,您不能在构造函数中执行此操作):

因为你没有等待——下一个声明

this.CarList = new QueryableCollectionView(this.carList, typeof(Car));
在初始化
之前执行(可能)。carList
。因此,当该行执行时,
this.carList
为空,很可能导致您的问题

因此,如果要从构造函数中执行此操作,则需要执行以下操作:

private async Task Initialize() {
    try {
          await this.RefreshCarListAsync("") // Doesn't show any data
          this.CarList = new QueryableCollectionView(this.carList, typeof(Car));
    }
    catch (Exception ex) {
         // do something meaningful, otherwise it will go unnoticed
    }
}

从构造函数调用它。或者更好—公开它,不要从构造函数调用它,而是让使用viewmodel的任何对象调用它,因为它可能会等待它。

如果在构造函数返回后动态设置属性,您应该在
MainWindowViewModel
类中实现
INotifyPropertyChanged
并引发
PropertyChanged
事件:

public class MainWindowViewModel : INotifyPropertyChanged
{
    private ICollectionView  carList;
    public ICollectionView  CarList
    {
        get { return carList; }
        private set { carList = value; NotifyPropertyChanged(); }
    }

    private DataReceivedHandler dataReceivedHandler = new DataReceivedHandler();

    public async Task Initialise()
    {
        try
        {
            await this.CarListAsync("");
            this.CarList = new QueryableCollectionView(this.carList, typeof(Car));
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex);
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    // This method is called by the Set accessor of each property.  
    // The CallerMemberName attribute that is applied to the optional propertyName  
    // parameter causes the property name of the caller to be substituted as an argument.  
    private void NotifyPropertyChanged([CallerMemberName] string propertyName = "")
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

在构造函数中调用异步方法对我来说没有意义。它将允许您在构造函数完成之前使用对象,这可能是您的问题。为什么它必须是异步的?您不能从构造函数进行任何异步调用。考虑公开一个<代码>公共异步任务初始化()<代码>方法,在构建之后被调用和等待。是否<代码>这个?CarListAsync(“”)< /C>不返回一个不应该忽略的值吗?类似于
carList=await CarListAsync(“”)?另外,
this.viewModel.Initialise()应该是
wait viewModel.Initialise()从构造函数调用
Initialize()
也很糟糕。应该等待它,但在构造函数中不能这样做。任何异步的东西都不属于这里。这就是为什么我添加了那么大的IF。若不是从构造函数调用,那个么它很有可能是从事件处理程序或其他无论如何都不能等待的地方调用的,因为这是UI框架。在这种情况下,很高兴知道您至少必须处理潜在的异常。我只是将Initialize方法公开,并在构建视图模型后调用并等待它。@Clemens我已尝试将Initialize方法公开,并执行Evk建议的代码,但仍然无法处理此错误,无法将类型ObservableCollection隐式转换为ICollectionViewWell,这是您的代码。然后将字段更改为
ICollectionView
。关键是你应该实现
INotifyPropertyChanged
。这就解决了这个问题。谢谢@mm8
this.RefreshCarListAsync("") // Doesn't show any data
this.CarList = new QueryableCollectionView(this.carList, typeof(Car));
private async Task Initialize() {
    try {
          await this.RefreshCarListAsync("") // Doesn't show any data
          this.CarList = new QueryableCollectionView(this.carList, typeof(Car));
    }
    catch (Exception ex) {
         // do something meaningful, otherwise it will go unnoticed
    }
}
public class MainWindowViewModel : INotifyPropertyChanged
{
    private ICollectionView  carList;
    public ICollectionView  CarList
    {
        get { return carList; }
        private set { carList = value; NotifyPropertyChanged(); }
    }

    private DataReceivedHandler dataReceivedHandler = new DataReceivedHandler();

    public async Task Initialise()
    {
        try
        {
            await this.CarListAsync("");
            this.CarList = new QueryableCollectionView(this.carList, typeof(Car));
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex);
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    // This method is called by the Set accessor of each property.  
    // The CallerMemberName attribute that is applied to the optional propertyName  
    // parameter causes the property name of the caller to be substituted as an argument.  
    private void NotifyPropertyChanged([CallerMemberName] string propertyName = "")
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}