代码之家  ›  专栏  ›  技术社区  ›  Jason Coyne

如何从后台线程正确更新数据绑定的datagridview

  •  8
  • Jason Coyne  · 技术社区  · 16 年前

    我已经为集合创建了绑定源,并设置了bindingsource和datagridview的数据源。

    除了我需要从后台线程更新自定义对象的属性外,一切都很好。当我这样做时,我会得到以下错误:

    BindingSource不能是其自己的数据源。不要将DataSource和DataMember属性设置为引用回BindingSource的值

    http://social.msdn.microsoft.com/forums/en-US/winformsdatacontrols/thread/3566f7c7-eb47-422e-ab09-9549a18da360/

    我在我的业务对象中创建并初始化了每个post的oper变量,然后将这两个事件函数放入我的集合类中。此代码已正确编译,但在运行时会毫无例外地挂起。

    一个限制:我希望业务对象不知道是谁在显示它(因为有多个使用者),因此将GUI引用发送到业务对象中,以便我以后能够使用这些引用调用调用不是一个选项。

    3 回复  |  直到 12 年前
        1
  •  14
  •   Marc Gravell    15 年前

    我在一个有效的论坛上发现了这个类。只需使用这个而不是BindingList

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    using System.ComponentModel;
    using System.Threading;
    
    namespace Utility
    {
        public class ThreadedBindingList<T> : BindingList<T>
        {
            SynchronizationContext ctx = SynchronizationContext.Current;
    
            protected override void OnAddingNew(AddingNewEventArgs e)
            {
    
                if (ctx == null)
                {
                    BaseAddingNew(e);
                }
                else
                {
                    ctx.Send(delegate
                    {
                        BaseAddingNew(e);
                    }, null);
                }
            }
            void BaseAddingNew(AddingNewEventArgs e)
            {
                base.OnAddingNew(e);
            }
            protected override void OnListChanged(ListChangedEventArgs e)
            {
               // SynchronizationContext ctx = SynchronizationContext.Current;
                if (ctx == null)
                {
                    BaseListChanged(e);
                }
                else
                {
                    ctx.Send(delegate
                    {
                        BaseListChanged(e);
                    }, null);
                }
            }
            void BaseListChanged(ListChangedEventArgs e)
            {
                base.OnListChanged(e);
            }
        } 
    }
    
        2
  •  1
  •   VVS    16 年前

    由于我花了时间根据自己的需要对样本进行格式化,我不妨将其作为可读的参考发布在这里。除了格式外,没有任何更改。

    using System.ComponentModel; 
    using System.Threading;
    
    namespace Utility 
    {
      public class ThreadedBindingList : BindingList 
      {
        SynchronizationContext ctx = SynchronizationContext.Current;
        protected override void OnAddingNew(AddingNewEventArgs e)
        {
          if (ctx == null)
          {
            BaseAddingNew(e);
          }
          else
          {
            ctx.Send(delegate { BaseAddingNew(e); }, null);
          }
        }
    
        void BaseAddingNew(AddingNewEventArgs e)
        {
          base.OnAddingNew(e);
        }
    
        protected override void OnListChanged(ListChangedEventArgs e)
        {
          // SynchronizationContext ctx = SynchronizationContext.Current;
          if (ctx == null)
          {
            BaseListChanged(e);
          }
          else
          {
            ctx.Send(delegate { BaseListChanged(e); }, null);
          }
        }
    
        void BaseListChanged(ListChangedEventArgs e)
        {
          base.OnListChanged(e);
        }
      }
    }
    
        3
  •  0
  •   Jeremy Lakeman    10 年前

    protected override void OnListChanged(ListChangedEventArgs e)
    {
      // SynchronizationContext ctx = SynchronizationContext.Current;
      if (ctx == null)
      {
        BaseListChanged(e);
      }
      else if(e.ListChangedType == ListChangedType.ItemChanged)
      {
        ctx.Post(delegate { BaseListChanged(e); }, null);
      }
      else
      {
        ctx.Send(delegate { BaseListChanged(e); }, null);
      }
    }
    

    如果同一对象已被多次修改,欢迎提出任何减少已发送呼叫数的建议,并确保以后的任何发送呼叫都将被阻止,直到处理完所有已发送呼叫。