EnableCollectionSynchronization 如何工作?
How does EnableCollectionSynchronization work?
有几篇文章解释了 BindingOperations.EnableCollectionSynchronization 的用法。例如。 BindingOperations.EnableCollectionSynchronization mystery in WPF or Using 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
背景信息:当 运行 LINQ 查询频繁更改的 ObservableCollection 时,我偶尔会遇到 InvalidOperationExceptions“集合已修改”。这使我将其分解为上一个示例。然后我发现我对 EnableCollectionSynchronization 如何工作的假设是错误的。
您应该使用相同的锁同步 所有 对集合的访问,即您应该锁定对 Add
:
的调用
lock (itemsLock)
items.Add("foo");
documentation 对此非常清楚:
To use a collection on multiple threads, one of which is the UI thread that owns the ItemsControl
, an application has the following responsibilities:
- 选择同步机制。
- 使用该机制同步所有 从应用程序到集合的访问。
- 调用
EnableCollectionSynchronization
通知WPF机制
- ...
有几篇文章解释了 BindingOperations.EnableCollectionSynchronization 的用法。例如。 BindingOperations.EnableCollectionSynchronization mystery in WPF or Using 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
背景信息:当 运行 LINQ 查询频繁更改的 ObservableCollection 时,我偶尔会遇到 InvalidOperationExceptions“集合已修改”。这使我将其分解为上一个示例。然后我发现我对 EnableCollectionSynchronization 如何工作的假设是错误的。
您应该使用相同的锁同步 所有 对集合的访问,即您应该锁定对 Add
:
lock (itemsLock)
items.Add("foo");
documentation 对此非常清楚:
To use a collection on multiple threads, one of which is the UI thread that owns the
ItemsControl
, an application has the following responsibilities:
- 选择同步机制。
- 使用该机制同步所有 从应用程序到集合的访问。
- 调用
EnableCollectionSynchronization
通知WPF机制 - ...