C# 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

有几篇文章解释了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如何工作的假设是错误的。

您应该使用同一个锁同步对集合的所有访问,即您应该锁定要添加的调用:

关于这一点,我们的立场相当明确:

要在多个线程(其中一个线程是拥有ItemsControl的UI线程)上使用集合,应用程序有以下职责:

选择一种同步机制。 使用该机制同步应用程序对集合的所有访问。 调用EnableCollectionSynchronization以通知WPF该机制。 ...
真可耻,我一定是瞎了。不知何故,我认为BindingOperations.EnableCollectionSynchronization使我的ObservableCollection线程安全。然而,它所做的只是与WPF绑定共享锁对象。
lock (itemsLock)
    items.Add("foo");