The*_*per 6 c# multithreading winforms
这是我的观点:
我有一个绑定到BindingList的GridControl.起初我正在做的是创建一个工作线程并直接访问BindingList,但这是一个"检测到跨线程操作",所以我按照这里的指南:
http://www.devexpress.com/Support/Center/p/AK2981.aspx
通过将原始BindingList克隆到工作线程并更改那个,我得到了预期的效果.但是,我最近将INotifyPropertyChanged实现到了绑定到BindingList的对象中,然后我又开始收到错误.
我的猜测是GridView仍在从对象中侦听INotifyPropertyChanged.
我怎样才能解决这个问题?
我的课:
public class Proxy : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    protected void OnPropertyChanged(string name)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(name));
        }
    }
The*_*ing 10
如果您从UI线程外部(例如从工作线程)操作UI,则需要重新加入UI线程.您可以通过调用InvokeUI控件来完成此操作.您可以使用测试是否需要这样做InvokeRequired.
通常使用的模式是:
public void ChangeText(string text)
{
   if(this.InvokeRequired)
   {
      this.Invoke(new Action(() => ChangeText(text)));
   }
   else
   {
      label.Text = text;  
   }
}
在您的情况下,UI正在被操纵INotifyPropertyChanged,因此您需要确保始终在UI线程上修改您的实体(使用上述技术),或使用通用异步INotifyPropertyChanged帮助程序.这是绑定项目的包装器.它使用上述技术来确保ChangeProperty在UI线程上触发事件.
这是一个非常粗略的Entity类代理示例.这可确保属性更改事件重新加入UI线程,并使实体本身保持不变.显然,您可能希望使用DynamicObject更具体地实现它.
public class NotificationHelper : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    private readonly ISynchronizeInvoke invokeDelegate;
    private readonly Entity entity;
    public NotificationHelper(ISynchronizeInvoke invokeDelegate, Entity entity)
    {
       this.invokeDelegate = invokeDelegate;
       this.entity = entity;
       entity.PropertyChanged += OnPropertyChanged;
    }
    public string Name
    {
       get { return entity.Name; }
    }
    private void OnPropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        if (PropertyChanged != null)
        {
           if (invokeDelegate.InvokeRequired)
           {
               invokeDelegate.Invoke(new PropertyChangedEventHandler(OnPropertyChanged),
                                     new[] { sender, e });
               return;
           }
           PropertyChanged(this, e);
        }
     }
 }
我对 TheGateKeeper 的最终解决方案采取了类似的方法。但是,我绑定到许多不同的对象。所以我需要一些更通用的东西。解决方案是创建一个也实现了 ICustomTypeDescriptor 的包装器。通过这种方式,我不需要为可以在 UI 中显示的所有内容创建包装器属性。
public class SynchronizedNotifyPropertyChanged<T> : INotifyPropertyChanged, ICustomTypeDescriptor
    where T : INotifyPropertyChanged
{
    private readonly T _source;
    private readonly ISynchronizeInvoke _syncObject;
    public SynchronizedNotifyPropertyChanged(T source, ISynchronizeInvoke syncObject)
    {
        _source = source;
        _syncObject = syncObject;
        _source.PropertyChanged += (sender, args) => OnPropertyChanged(args.PropertyName);
    }
    public event PropertyChangedEventHandler PropertyChanged;
    protected virtual void OnPropertyChanged(string propertyName)
    {
        if (PropertyChanged == null) return;
        var handler = PropertyChanged;
        _syncObject.BeginInvoke(handler, new object[] { this, new PropertyChangedEventArgs(propertyName) });
    }
    public T Source { get { return _source; }}
    #region ICustomTypeDescriptor
    public AttributeCollection GetAttributes()
    {
        return new AttributeCollection(null);
    }
    public string GetClassName()
    {
        return TypeDescriptor.GetClassName(typeof(T));
    }
    public string GetComponentName()
    {
        return TypeDescriptor.GetComponentName(typeof (T));
    }
    public TypeConverter GetConverter()
    {
        return TypeDescriptor.GetConverter(typeof (T));
    }
    public EventDescriptor GetDefaultEvent()
    {
        return TypeDescriptor.GetDefaultEvent(typeof (T));
    }
    public PropertyDescriptor GetDefaultProperty()
    {
        return TypeDescriptor.GetDefaultProperty(typeof(T));
    }
    public object GetEditor(Type editorBaseType)
    {
        return TypeDescriptor.GetEditor(typeof (T), editorBaseType);
    }
    public EventDescriptorCollection GetEvents()
    {
        return TypeDescriptor.GetEvents(typeof(T));
    }
    public EventDescriptorCollection GetEvents(Attribute[] attributes)
    {
        return TypeDescriptor.GetEvents(typeof (T), attributes);
    }
    public PropertyDescriptorCollection GetProperties()
    {
        return TypeDescriptor.GetProperties(typeof (T));
    }
    public PropertyDescriptorCollection GetProperties(Attribute[] attributes)
    {
        return TypeDescriptor.GetProperties(typeof(T), attributes);
    }
    public object GetPropertyOwner(PropertyDescriptor pd)
    {
        return _source;
    }
    #endregion ICustomTypeDescriptor
}
然后在 Ui 中,我使用以下内容绑定到此包装器:
    private void CreateBindings()
    {
        if (_model == null) return;
        var threadSafeModel = new SynchronizedNotifyPropertyChanged<MyViewModel>(_model, this);
        directiveLabel.DataBindings.Add("Text", threadSafeModel, "DirectiveText", false, DataSourceUpdateMode.OnPropertyChanged);
    }
MyViewModel 有一个“DirectiveText”属性并实现了 INotifyPropertyChanged,没有特别考虑线程或视图类。
| 归档时间: | 
 | 
| 查看次数: | 10148 次 | 
| 最近记录: |