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"/>
效果很好。
现在我为员工建立了一个搜索功能,可以在所有成本中心找到他们。如果找到一个,我需要以编程方式更改 SelecedCostcentre
和 SelectedEmployee
。
这不会造成竞争条件吗?因为如果我设置 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
,没有任何竞争条件。
我的场景:有两个组合框绑定 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"/>
效果很好。
现在我为员工建立了一个搜索功能,可以在所有成本中心找到他们。如果找到一个,我需要以编程方式更改 SelecedCostcentre
和 SelectedEmployee
。
这不会造成竞争条件吗?因为如果我设置 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
,没有任何竞争条件。