即使在.NET 4.5中,ObservableCollection也不是线程安全的? [英] ObservableCollection not thread-safe even in .NET 4.5?

查看:44
本文介绍了即使在.NET 4.5中,ObservableCollection也不是线程安全的?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

几天来,我的头一直撞在虚拟墙上.BindingOperations.EnableSynchronization方法似乎在.NET 4.5中仅部分起作用.

I am banging my head against the virtual wall for days now. The BindingOperations.EnableSynchronization method seems to work only partial in .NET 4.5.

我写的测试有时会失败:

I wrote a test that fails sometimes:

        object blah = new object();

        Application app = Application.Current == null ? new Application() : Application.Current;
        SynchronizationContext.SetSynchronizationContext(new SynchronizationContext());
        ObservableCollection<ThreadSafeObservableTestObject> collection = null;
        collection = new ObservableCollection<ThreadSafeObservableTestObject>();

        BindingOperations.EnableCollectionSynchronization(collection, blah);

        CollectionTestWindow w = new CollectionTestWindow();

        Task.Factory.StartNew(() =>
        {
            Thread.Sleep(2000);
            w.TestCollection = collection;
            collection.CollectionChanged += collection_CollectionChanged;
            collection.Add(new ThreadSafeObservableTestObject() { ID = 1, Name = "Sandra Bullock" });
            collection.Add(new ThreadSafeObservableTestObject() { ID = 2, Name = "Jennifer Aniston" });
            collection.Add(new ThreadSafeObservableTestObject() { ID = 3, Name = "Jennifer Lopez" });
            collection.Add(new ThreadSafeObservableTestObject() { ID = 4, Name = "Angelina Jolie" });
            collection.Add(new ThreadSafeObservableTestObject() { ID = 5, Name = "Mary Elizabeth Mastrantonio" });
            Thread.Sleep(5000);
            System.Windows.Application.Current.Dispatcher.Invoke(() => w.Close());
            System.Windows.Application.Current.Dispatcher.Invoke(() => Application.Current.Shutdown());
        });
        app.Run(w);

TestCollectionWindow看起来像这样:

The TestCollectionWindow looks like this:

    <ItemsControl ItemsSource="{Binding TestCollection}" Name="list">
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <StackPanel Orientation="Horizontal">
                    <TextBlock Text="{Binding Name}" />
                    <TextBlock Text="{Binding ID}" />
                </StackPanel>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>

所以这里没什么魔术.但是结果几乎是每当某些条目在UI中两次出现-相同的对象!结果窗口如下所示:

So nothing magic here. But the result is almost every time that some entries are twice in the UI - the same objects! The result window looks like this then:

桑德拉·布洛克1
珍妮弗·安妮斯顿2
珍妮佛·洛佩兹(Jennifer Lopez)3
安吉丽娜·朱莉(Angelina Jolie)4
玛丽·伊丽莎白·马斯特拉通尼奥5
珍妮弗·安妮斯顿2

Sandra Bullock 1
Jennifer Aniston 2
Jennifer Lopez 3
Angelina Jolie 4
Mary Elizabeth Mastrantonio 5
Jennifer Aniston 2

您可以清楚地看到Jennifer Aniston列出了两次.这可以很容易地重现.这是一个普遍的问题,还是该测试有任何问题,例如错误的应用程序实例化?

As you can clearly see Jennifer Aniston is listed twice. This can be reproduced easily. Is this a general problem or is there anything wrong with this test, such as a flawed application instantiation?

提前谢谢!

推荐答案

该类为已记录不是线程安全的:

The class is documented to not be thread-safe:

线程安全
此类型的任何公共静态(在Visual Basic中为Shared)成员都是线程安全的.不保证任何实例成员都是线程安全的.

Thread Safety
Any public static (Shared in Visual Basic) members of this type are thread safe. Any instance members are not guaranteed to be thread safe.

所以不,它不是线程安全的.

So no, it is not thread-safe.

请注意, BindingOperations.EnableCollectionSynchronization 不会神奇地使整个集合变得神奇线程安全的.它只会告诉绑定系统您打算使用哪个锁定对象,以防止多个线程同时访问该集合.

Note that BindingOperations.EnableCollectionSynchronization does not magically make the entire collection thread-safe. It only tells the binding system which locking object that you intend to use in order to prevent multiple threads accessing the collection at the same time.

由于实际上并没有使用锁定对象,因此您最好不调用该方法,结果将同样不可预测.

Since you're not actually using the locking object, you might as well not call that method, the results will be equally unpredictable.

尝试在每个访问集合的语句周围的 blah 对象上发出 lock .不幸的是,我不知道WPF中有关数据绑定的详细信息,所以我不知道这是否足够.

Try issuing a lock on the blah object around each statement that accesses the collection. Unfortunately the details around data binding in WPF is unknown to me, so I have no idea if that is enough.

这篇关于即使在.NET 4.5中,ObservableCollection也不是线程安全的?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆