打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

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

         为了解决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;        }    }

 

来源:http://www.icode9.com/content-4-27351.html
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
INotifyPropertyChanged 接口用法
SL WPF仿WIN8进度条
[C#]手把手教你打造Socket的TCP通讯连接(一)
你可能写了个假异步,并不能提高请求线程池的吞吐量
MVVM基础概念及一个简单的样例
C#使用Emgu CV来进行图片人脸检测
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服