从另一个线程修改对象属性时引发OnPropertyChanged [英] Raising OnPropertyChanged when an object property is modified from another thread

查看:230
本文介绍了从另一个线程修改对象属性时引发OnPropertyChanged的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以我有这个对象:

public class SomeObject: INotifyPropertyChanged
{
         public decimal AlertLevel {
            get {
                return alertLevel;
            }
            set {
                if(alertLevel == value) return;
                alertLevel = value;
                OnPropertyChanged("AlertLevel");
            }

         private void OnPropertyChanged(string propertyName) {
            if(PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
}

假设我正在不是GUI线程的线程上更改此对象.当我在此类中没有任何GUI组件的引用时,如何让该对象在与GUI相同的线程上引发PropertyChanged事件?

Suppose I am changing this object on a thread that is NOT the GUI thread. How can I have this object raise the PropertyChanged event on the same thread as the GUI when I don't have a reference to any GUI component in this class?

推荐答案

一个更好的主意,不使用任何WPF引用:

public class GUIThreadDispatcher {
        private static volatile GUIThreadDispatcher itsSingleton;
        private WeakReference itsDispatcher;

        private GUIThreadDispatcher() { }

        public static GUIThreadDispatcher Instance
        {
            get
            {
                if (itsSingleton == null)
                    itsSingleton = new GUIThreadDispatcher();

                return itsSingleton;
            }
        }

        public void Init(Control ctrl) {
            itsDispatcher = new WeakReference(ctrl);
        }

        public void Invoke(Action method) {
            ExecuteAction((Control ctrl) => DoInGuiThread(ctrl, method, forceBeginInvoke: false));
        }

        public void BeginInvoke(Action method) {
            ExecuteAction((Control ctrl) => DoInGuiThread(ctrl, method, forceBeginInvoke: true));
        }

        private void ExecuteAction(Action<Control> action) {
            if (itsDispatcher.IsAlive) {
                var ctrl = itsDispatcher.Target as Control;
                if (ctrl != null) {
                    action(ctrl);
                }
            }
        }

        public static void DoInGuiThread(Control ctrl, Action action, bool forceBeginInvoke = false) {
            if (ctrl.InvokeRequired) {
                if (forceBeginInvoke)
                    ctrl.BeginInvoke(action);
                else
                    ctrl.Invoke(action);
            }
            else {
                action();
            }
        }
    }
}

并像这样初始化:

  private void MainForm_Load(object sender, EventArgs e) {

     //setup the ability to use the GUI Thread when needed via a static reference
     GUIThreadDispatcher.Instance.Init(this);  
     ...
  }

并像这样使用:

public class SomeObject: INotifyPropertyChanged
{
         public decimal AlertLevel {
            get {
                return alertLevel;
            }
            set {
                if(alertLevel == value) return;
                alertLevel = value;
                OnPropertyChanged("AlertLevel");
            }

          private void OnPropertyChanged(string propertyName) {
              GUIThreadDispatcher.Instance.BeginInvoke(() => {
              if (PropertyChanged != null)
                    PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
                });
        }}

这篇关于从另一个线程修改对象属性时引发OnPropertyChanged的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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