C# EnableCollectionSynchronization是如何工作的?
有几篇文章解释了BindingOperations.EnableCollectionSynchronization的用法。例如,或 但是,我对锁的理解与下面演示的行为不匹配C# EnableCollectionSynchronization是如何工作的?,c#,wpf,observablecollection,C#,Wpf,Observablecollection,有几篇文章解释了BindingOperations.EnableCollectionSynchronization的用法。例如,或 但是,我对锁的理解与下面演示的行为不匹配 private void Button_Click(object sender, RoutedEventArgs e) { var itemsLock = new object(); var items = new ObservableCollection<string>(); Bindi
private void Button_Click(object sender, RoutedEventArgs e)
{
var itemsLock = new object();
var items = new ObservableCollection<string>();
BindingOperations.EnableCollectionSynchronization(items, itemsLock);
Task.Run(() =>
{
lock (itemsLock)
{
Debug.WriteLine("task inside lock");
Thread.Sleep(5000);
items.Where(m => m == "foo").ToArray();
}
Debug.WriteLine("task outside lock");
});
Thread.Sleep(1000);
Debug.WriteLine("UI thread add..");
items.Add("foo");
Debug.WriteLine("UI thread add..done");
}
但我发现调试输出如下:
task inside lock
UI thread add..
task outside lock
UI thread add..done
task inside lock
UI thread add..
UI thread add..done
task outside lock
背景信息:我偶尔体验到,在频繁更改的ObservableCollection上运行LINQ查询时,InvalidOperationExceptions集合被修改。这导致我将其分解为上一个样本。然后,我发现我对EnableCollectionSynchronization如何工作的假设是错误的。您应该使用同一个锁同步对集合的所有访问,即您应该锁定要添加的调用:
关于这一点,我们的立场相当明确:
要在多个线程(其中一个线程是拥有ItemsControl的UI线程)上使用集合,应用程序有以下职责:
选择一种同步机制。
使用该机制同步应用程序对集合的所有访问。
调用EnableCollectionSynchronization以通知WPF该机制。
...
真可耻,我一定是瞎了。不知何故,我认为BindingOperations.EnableCollectionSynchronization使我的ObservableCollection线程安全。然而,它所做的只是与WPF绑定共享锁对象。
lock (itemsLock)
items.Add("foo");