c# - EnableCollectionSynchronization 如何工作?
问题描述
有几篇文章解释了 BindingOperations.EnableCollectionSynchronization 的用法。例如WPF 中的 BindingOperations.EnableCollectionSynchronization 之谜或使用 BindingOperations.EnableCollectionSynchronization
但是,我对“锁”的理解与以下演示的行为不符。
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 工作原理的假设是错误的。
解决方案
您应该使用相同的锁同步对集合的所有访问,即您应该锁定调用Add
:
lock (itemsLock)
items.Add("foo");
文档对此非常清楚:
要在多个线程(其中一个是拥有 的 UI 线程)上使用集合,
ItemsControl
应用程序具有以下职责:
- 选择一种同步机制。
- 使用该机制同步从应用程序到集合的所有访问。
- 调用
EnableCollectionSynchronization
以通知 WPF 该机制。 - ...
推荐阅读
- java - Runtime.getRuntime.exec() 无法正常工作
- php - 如何在 laravel 中使用两个链接表实现多用户(4 种用户类型)身份验证 - 角色和用户
- javascript - 需要将重点放在 div 上进行反应
- spring - 春季批次:子步骤的概念?
- excel - VBA 复制粘贴循环
- c++ - 是否使用 c++ && (AND) 运算符进行排序
- angular - 如何更新promise中的全局变量并返回到其他组件中使用
- reactjs - 如何在反应中呈现PDF?
- php - 如何在 codeigniter 中使用 Find_IN_SET?
- .net - 使用 Google API 上传 Excel 文件是否有最大大小?