当前位置: 首页 > 编程语言 > C#

INotifyPropertyChanged导致跨线程错误分享

时间:2023-04-10 23:38:46 C#

INotifyPropertyChanged导致跨线程错误这是我的看法:我有一个绑定到BindingList的GridControl。起初我正在做的是创建一个工作线程并直接访问BindingList,但这是“检测到的跨线程操作”,所以我遵循了这里的指南:http://www.devexpress.com/Support/Center/p/AK2981.aspx我通过将原始BindingList克隆到工作线程并更改它来获得预期的效果。但是,我最近将INotifyPropertyChanged实现到绑定到BindingList的对象中,我又开始出错了。我的猜测是GridView仍在侦听对象的INotifyPropertyChanged。我怎么解决这个问题?我的班级:公共班级代理:INotifyPropertyChanged{公共事件PropertyChangedEventHandlerPropertyChanged;protectedvoidOnPropertyChanged(stringname){PropertyChangedEventHandlerhandler=PropertyChanged;if(handler!=null){handler(this,newPropertyChangedEvent(name))Args;您从UI线程之外(例如从工作线程)操作UI,您需要重新加入UI线程。您可以通过在UI控件上调用Invoke来完成此操作。您可以使用InvokeRequired来测试是否需要InvokeRequired。一个常用的模式是:publicvoidChangeText(stringtext){if(this.InvokeRequired){this.Invoke(newAction(()=>ChangeText(text)));}else{label.Text=text;在您的情况下,由于INotifyPropertyChanged正在操纵UI,因此您需要确保始终在UI线程上修改实体(使用上述技术),或者使用通用的异步INotifyPropertyChanged帮助程序。这是绑定项目的包装器。它使用上述技术来确保ChangeProperty事件在UI线程上触发。这是实体类代理的一个非常粗略的示例。这确保属性更改事件重新加入UI线程并保持实体本身不变。显然,您可能希望使用DynamicObject更具体地实现它。公共类NotificationHelper:INotifyPropertyChanged{公共事件PropertyChangedEventHandlerPropertyChanged;私有只读ISynchronizeInvokeinvokeDelegate;私有只读实体实体;publicNotificationHelper(ISynchronizeInvokeinvokeDelegate,Entityentity){this.invokeDelegate=invokeDelegate;this.entity=实体;entity.PropertyChanged+=OnPropertyChanged;}publicstringName{get{returnentity.Name;}}privatevoidOnPropertyChanged(objectsender,PropertyChangedEventArgse){if(PropertyChanged!=null){if(invokeDelegate.InvokeRequired){invokeDelegate.Invoke(newPropertyChangedEventArgse){new[]{sender,e});返回;}PropertyChanged(this,e);我对TheGateKeeper的最终解决方案采用了类似的方法。但是,我绑定了许多不同的对象。所以我需要更通用的东西。解决方案是创建一个也实现ICustomTypeDescriptor的包装器。这样我就不需要为可以在UI中显示的所有内容创建包装器属性。公共类SynchronizedNotifyPropertyChanged:INotifyPropertyChanged,ICustomTypeDescriptor其中T:INotifyPropertyChanged{privatereadonlyT_source;私人只读ISynchronizeInvoke_syncObject;publicSynchronizedNotifyPropertyChanged(Tsource,ISynchronizeInvokesyncObject){_source=source;_syncObject=同步对象;_source.PropertyChanged+=(sender,args)=>OnPropertyChanged(args.PropertyName);}公共事件PropertyChangedEventHandlerPropertyChanged;protectedvirtualvoidOnPropertyChanged(stringpropertyName){if(PropertyChanged==null)返回;varhandler=PropertyChanged;_syncObject.BeginInvoke(handler,newobject[]{this,newPropertyChangedEventArgs(propertyName)});}publicTSource{get{return_source;}}#regionICustomTypeDescriptorpublicAttributeCollectionGetAttributes(){返回新的AttributeCollection(null);}publicstringGetClassName(){returnTypeDescriptor.GetClassName(typeof(T));}民众字符串GetComponentName(){returnTypeDescriptor.GetComponentName(typeof(T));}publicTypeConverterGetConverter(){returnTypeDescriptor.GetConverter(typeof(T));}publicEventDescriptorGetDefaultEvent(){returnTypeDescriptor.GetDefaultEvent(typeof(T));}publicPropertyDescriptorGetDefaultProperty(){returnTypeDescriptor.GetDefaultProperty(typeof(T));}publicobjectGetEditor(TypeeditorBaseType){returnTypeDescriptor.GetEditor(typeof(T),editorBaseType);}publicEventDescriptorCollectionGetEvents(){returnTypeDescriptor.GetEvents(typeof(T));}publicEventDescriptorCollectionGetEvents(Attribute[]attributes){returnTypeDescriptor.GetEvents(typeof(T),attributes);}publicPropertyDescriptorCollectionGetProperties(){returnTypeDescriptor.GetProperties(typeof(T));}publicPropertyDescriptorCollectionGetProperties(Attribute[]attributes){returnTypeDescriptor.GetProperties(typeof(T),attributes);}公共对象GetPropertyOwner(PropertyDescriptorpd){返回_source;}#endregionICustomTypeDescriptor}然后在Ui中,我使用类似以下内容绑定到此包装器:privatevoidCreateBindings(){if(_model==null)return;varthreadSafeModel=newSynchronizedNotifyPropertyChanged(_model,this);directiveLabel.DataBindings.Add("Text",threadSafeModel,"DirectiveText",false,DataSourceUpdateMode.OnPropertyChanged);}MyViewModel有一个“DirectiveText”属性并实现了INotifyPropertyChanged,对线程或视图类没有特别的考虑一旦有人遇到同样的问题......我在几个小时后设法修复了它。这是我所做的:基本上问题是实现INotifyPropertyChanged的??对象存在于工作线程中,这在访问UI线程时会导致问题。所以我所做的是将需要更新的对象的引用传递给INotifyPropertyChanged对象,然后调用它。这就是它的样子:公共事件PropertyChangedEventHandlerPropertyChanged;protectedvoidOnPropertyChanged(stringname){PropertyChangedEventHandlerhandler=PropertyChanged;if(handler!=null){//如果Proxy对象在非UI线程中,使用invokeif(c!=null){c.BeginInvoke(newAction(()=>handler(this,newPropertyChangedEventArgs(姓名))));}//否则直接更新else{handler(this,newPropertyChangedEventArgs(name));}}}//当需要publicControlC{set{c=value;时使用this来引用UI线程上的对象从线程的角度来看,我所做的就是:prox.c=this;//这里的逻辑prox.c=null;希望这对某人有帮助!我将BindingList子类化,以便我可以检查所需的Invoke。这样我的业务对象就没有对UI的引用。以上就是C#学习教程的全部内容:INotifyPropertyChanged导致跨线程错误共享。如果对大家有用,需要进一步了解C#学习教程,希望大家多加关注——控制=控制;}publicInvokingBindingList(Controlcontrol=null){this.Control=control;}公共控制控制{得到;放;}protectedoverridevoidOnListChanged(ListChangedEventArgse){if(Control?.InvokeRequired==true)Control.Invoke(newAction(()=>base.OnListChanged(e)));否则base.OnListChanged(e);}}本文收集自网络,不代表立场。如涉及侵权,请点击右侧联系管理员删除。如需转载请注明出处: