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

Jas*_*yne 8 c# data-binding multithreading datagridview inotifypropertychanged

我有一个实现INotifyPropertyChanged的自定义对象.我有这些对象的集合,其中集合基于BindingList我已经为集合创建了一个绑定源,并设置了bindingsource和datagridview的数据源.

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

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

我发现以下帖子似乎有我的确切问题(和解决方案?)但我无法弄明白.

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

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

我看过许多帖子说使用Invoke/Begin Invoke,但是我没有调用UI上的任何函数,只是更新业务对象,所以我不确定在哪里调用invoke.

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

Jas*_*yne 14

我在一个有效的论坛中找到了这个课程.只需使用它而不是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);
        }
    } 
}
Run Code Online (Sandbox Code Playgroud)