为什么 CollectionChanged 不是线程安全的? [英] Why is CollectionChanged not threadsafe?

查看:72
本文介绍了为什么 CollectionChanged 不是线程安全的?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发一个 WPF 应用程序,发现绑定属性上的属性更改通知可以从后台线程发生,但是对 observablecollection 进行任何更改(如添加或删除项目)必须从 UI 线程发生.我的问题是为什么会这样?INotifyPropertyChanged 和 INotifyCollectionChanged 都是 UI 控件订阅的,那为什么 INotifyPropertyChanged 会出现异常?

I'm working on a WPF application and found that property changed notifications on binded properties can happen from a background thread, however for making any change to an observablecollection(like adding or removing item) has to happen from a UI thread. My question is why is it so? Both INotifyPropertyChanged and INotifyCollectionChanged are subscribed by UI controls, then why an exception for INotifyPropertyChanged?

例如:

 public class ViewModel : INotifyPropertyChanged
    {
        ObservableCollection<Item> _items = new ObservableCollection<Item>();

        private string _name;
        public string Name
        {
            get { return _name; }
            set
            {
                _name = value;
                //Can fire this from a background thread without any crash and my 
                //Name gets updated in the UI
                InvokePropertyChanged(new PropertyChangedEventArgs("Name"));
            }
        }

        public void Add(Item item)
        {
            //Cant do this from a background thread and has to marshal.
            _items.Add(item);
        }

        public event PropertyChangedEventHandler PropertyChanged;

        public void InvokePropertyChanged(PropertyChangedEventArgs e)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null) handler(this, e);
        }
    }

注意:来自后台线程的 CollectionChanged 事件使应用程序崩溃,但是来自后台线程的 PropertyChanged 事件更新 UI 没有任何问题,是的,这是在 .NET 4.0 中

NOTE: CollectionChanged event from a background thread crashes the app, however PropertyChanged event from a background thread updates the UI without any issues and yes, this is in .NET 4.0

推荐答案

此问题与线程安全无关.问题是 CollectionChanged 事件是从工作线程引发的,这意味着处理程序在同一个线程中执行,当处理程序尝试触摸 UI 时,您会遇到异常,因为这仅允许从界面线程.

This problem is not related to thread safety. The issue is that the CollectionChanged event is raised from a worker thread, which means the handlers are executed in that same thread, and when a handler tries to touch the UI you have an exception because that's only allowed from the UI thread.

如果情况相同,PropertyChanged 事件也会发生同样的情况,没有对任一事件给予特殊处理.

The same would also happen for the PropertyChanged event if the situation were identical, there is no special treatment being given to either event.

如果您需要从事件处理程序中触摸 UI,那么您必须确保 在 UI 线程上引发事件 否则事件处理程序必须检查 Dispatcher.CheckAccess 是否需要对 UI 线程进行编组更改,并且 Dispatcher.BeginInvoke 这样做.

If you need to touch the UI from within your event handlers then you have to either make sure the event is raised on the UI thread or else the event handlers have to check with Dispatcher.CheckAccess if marshalling changes to the UI thread is needed and Dispatcher.BeginInvoke to do so.

这篇关于为什么 CollectionChanged 不是线程安全的?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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