INotifyPropertyChanged 的​​竞争条件 - c#

Race condition with INotifyPropertyChanged - c#

我的场景:有两个组合框绑定 SelectedItem 属性。 第一个组合框包含成本中心,第二个组合框包含所选成本中心的员工。

这意味着如果 SelectedCostcentre 发生变化,INotifyPropertyChanged 将解雇并搜索成本中心的所有员工。

视图模型:

  public abstract class SelectEmployeeViewModel : ViewModelBase
{
    protected readonly Plant plant;

    public ObservableCollection<Costcentre> Costcentres { get; protected set; }
    public Costcentre SelectedCostcentre { get; set; }
    public ObservableCollection<Employee> Employees { get; protected set; }
    public Employee SelectedEmployee { get; set; }

    public bool CostcentresEnabled
    {
        get { return Costcentres != null && Costcentres.Any(); }
    }
    public bool EmployeesEnabled
    {
        get { return Employees != null && Employees.Any(); }
    }

    protected SelectEmployeeViewModel(Window window, Page page, Plant plant) : base(window, page)
    {
        this.plant = plant;

        PropertyChanged += SelectEmployeeViewModel_PropertyChanged;
        Costcentres = mainController.CostcentreDao.GetByPlant(plant);
    }

    private void SelectEmployeeViewModel_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
    {
        switch (e.PropertyName)
        {
            case nameof(SelectedCostcentre):
                SetEmployees();
                break;
        }
    }

    private void SetEmployees()
    {
        if (SelectedCostcentre != null)
            Employees = mainController.EmployeeDao.GetByCostcentre(SelectedCostcentre);
        else
            Employees = new ObservableCollection<Employee>();
    }
}

Xaml:

   <ComboBox
        ItemsSource="{Binding Costcentres}"
        SelectedItem="{Binding SelectedCostcentre}"
        DisplayMemberPath="DisplayName"
        HorizontalAlignment="Left"
        IsEnabled="{Binding CostcentresEnabled}"
        Margin="81,61,0,0" VerticalAlignment="Top" Width="213"/>
    <ComboBox
        ItemsSource="{Binding Employees}"
        SelectedItem="{Binding SelectedEmployee}"
        DisplayMemberPath="DisplayName"
        IsEnabled="{Binding EmployeesEnabled}"
        HorizontalAlignment="Left" Margin="81,88,0,0" VerticalAlignment="Top" Width="213"/>

效果很好。 现在我为员工建立了一个搜索功能,可以在所有成本中心找到他们。如果找到一个,我需要以编程方式更改 SelecedCostcentreSelectedEmployee

这不会造成竞争条件吗?因为如果我设置 SelectedCostcentre 属性 PropertyChanged 触发并设置 Employees 属性.

  private void SetEmployee(Employee employee)
    {
        SelectedCostcentre = Costcentres.Single(x => x.Id == employee.Costcentre.Id);
        SelectedEmployee = Employees.Single(x => x.Id == employee.Id);
    }

如何在没有竞争条件的情况下解决这个问题?

谢谢

没有竞争条件,因为整个事情发生在一个线程上。

SelectedCostcentre = Costcentres.Single(x => x.Id == employee.Costcentre.Id);

SelectedCostcentre 属性 的第一个 setter 被执行,它调用 PropertyChanged (在你的代码中我没有看到它,但我认为这只是一个错字).这依次调用 SelectEmployeeViewModel_PropertyChanged 处理程序和 SetEmployees。因此,在执行上面的行之后 - Employees 被同步填充给定的选定 Costcenter,没有任何竞争条件。