NotifyPropertyChanged线程与界面绑定异步更新

版权声明:未经允许,不可转载。 https://blog.csdn.net/zhengxu25689/article/details/82877545

         为了解决NotifyPorpertyChanged的线程与界面绑定异步更新冲突问题,所以查看相关资料后,将自己的NotifyPropertyChanged作了改进。

1.问题起因

        在开发C#应用程序,通常后使用到界面控件特定属性(Enable | Text)与指定的类成员绑定。但如果指定类成员变量在线程中和界面需异步更新时,会出现异常情况(界面显示异常)。

以下代码未作异步更新,示例如下:
 

  public class TubeConsumedRecord : INotifyPropertyChanged
    {

        /// <summary>
        /// The lock tube
        /// </summary>
        private object lockTube;
        /// <summary>
        /// The available count
        /// </summary>
        private int availableCount;
        /// <summary>
        /// 在属性值更改时发生。
        /// </summary>
        public event PropertyChangedEventHandler PropertyChanged;

        /// <summary>
        /// Gets or sets the available tube count.
        /// </summary>
        /// <value>The available tube count.</value>
        public int AvailableTubeCount
        {
            get
            {
                return availableCount;
            }

            set
            {
                if (this.availableCount == value)
                {
                    return;
                }
                this.availableCount = value;
                OnPropertyChanged(new PropertyChangedEventArgs("AvailableTubeCount"));
            }
        }
        /// <summary>
        /// Handles the <see cref="E:PropertyChanged" /> event.
        /// </summary>
        /// <param name="e">The <see cref="PropertyChangedEventArgs"/> instance containing the event data.</param>
        private void OnPropertyChanged(PropertyChangedEventArgs e)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, e);
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="TubeConsumedRecord"/> class.
        /// </summary>
        public TubeConsumedRecord()
        {
            this.lockTube = new object();
        }

    }

2. 解决方法

为了解决属性绑定的界面和线程异步更新时冲突问题,对INotifyPropertyChanged作了相应的改造。

改造后的类AsynNotifyPropertyChanged, 直接继承使用。

设置异步上下文类为SynchronizationContextProvider,需要用户设置界面的异步上下文,在创造主窗体Main()中添加。

 SynchronizationContextProvider.CreateSynchronizationContext(WindowsFormsSynchronizationContext.Current);

AsynNotifyPropertyChanged代码如下:

  public class AsynNotifyPropertyChanged : INotifyPropertyChanged
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="AsyncBindingData"/> class.
        /// </summary>
        public AsynNotifyPropertyChanged()
        {
        }

        /// <summary>
        /// Occurs when a property value changes.
        /// </summary>
        public event PropertyChangedEventHandler PropertyChanged;

        /// <summary>
        /// Called when [property changed].
        /// </summary>
        /// <param name="propertyName">Name of the property.</param>
        public void OnPropertyChanged(string propertyName)
        {
            
            if (this.PropertyChanged == null||string.IsNullOrEmpty(propertyName))
            {
                return;
            }
        
            if (SynchronizationContextProvider.UISynchronizationContext != null)
            {
                SynchronizationContextProvider.UISynchronizationContext.Send(new SendOrPostCallback(AysnPropertyChanged), propertyName);
            }
            else
            {
                this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        private void AysnPropertyChanged(object state)
        {
            string propertyName = state.ToString();
            if (this.PropertyChanged != null)
            {
                this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }


        public void OnPropertyChanged(object sender, PropertyChangedEventHandler propertyChanged, string propertyName)
        {
            if (propertyChanged == null || string.IsNullOrEmpty(propertyName))
            {
                return;
            }

            if (SynchronizationContextProvider.UISynchronizationContext != null)
            {
                SynchronizationContextProvider.UISynchronizationContext.Send(new SendOrPostCallback(AysnPropertyChanged), propertyName);
            }
            else
            {
                propertyChanged(sender, new PropertyChangedEventArgs(propertyName));
            }
        }
    }

SynchronizationContextProvider类代码如下:

  public  class SynchronizationContextProvider
    {
        /// <summary>
        /// The current
        /// </summary>
        private static SynchronizationContext current;

        /// <summary>
        /// Gets the UI synchronization context.
        /// </summary>
        /// <value>The UI synchronization context.</value>
        internal static SynchronizationContext UISynchronizationContext
        {
            get
            {
                if(SynchronizationContext.Current==null)
                {
                    SynchronizationContext.SetSynchronizationContext(current);
                }

                return current; 
            }
        }

        /// <summary>
        /// Creates the synchronization context.
        /// </summary>
        /// <param name="context">The context.</param>
        public static void CreateSynchronizationContext(SynchronizationContext context)
        {
            current = context;
        }
    }

猜你喜欢

转载自blog.csdn.net/zhengxu25689/article/details/82877545