C# 工作线程添加到BindingList时出现跨线程操作异常

C# 工作线程添加到BindingList时出现跨线程操作异常,c#,winforms,multithreading,data-binding,bindinglist,C#,Winforms,Multithreading,Data Binding,Bindinglist,我有一个工作线程,需要将项目添加到绑定列表。但是,BindingList被数据绑定到一个DataGridView。因此,当我尝试添加到列表中时,我得到了一个invalidoOperationException(跨线程操作无效:从创建控件的线程以外的线程访问控件)。 通常,对于此异常,您将执行以下操作: if(winformControl.InvokeRequired) { winformControl.Invoke(MethodDelegate); } 然而,数据绑定混淆了事情,因为没

我有一个工作线程,需要将项目添加到
绑定列表
。但是,
BindingList
被数据绑定到一个
DataGridView
。因此,当我尝试添加到列表中时,我得到了一个
invalidoOperationException(跨线程操作无效:从创建控件的线程以外的线程访问控件)。

通常,对于此异常,您将执行以下操作:

if(winformControl.InvokeRequired) {
    winformControl.Invoke(MethodDelegate);
}
然而,数据绑定混淆了事情,因为没有Winform控件。我只有下面一行,它抛出了异常:

ClassInstance.MyBindingList.Add(myObject);
如果您有专门针对此场景的解决方案,那就太好了


如果没有,我如何让工作线程告诉我的主线程执行特定的方法(工作线程提供了几个参数)?这可能是一个更好的选择,因为我的工作线程目前实际上正在做很多事情(比如写入数据库),我不确定是否所有事情都是线程安全的。我是一名学生,不熟悉多线程,但它还不是我的强项。

您可以向主、UI、线程触发事件,并且有:

if (this.InvokeRequired)
{
    this.Invoke(...);
}

因此,您正在主窗口本身上进行测试。

这里的一个选项是告诉
BindingList
使用同步上下文,-然而,这可能不是最好的方法。我想知道您是否可以通过事件或类似事件公开数据(而不是直接添加到列表中),然后让您的UI通过发送到正确的线程并添加到UI模型来处理事件。

在worker类构造函数中,尝试以下方法:

private System.Threading.SynchronizationContext mContext = null;

/// <summary>
/// Constructor for MyBackgroundWorkerClass
/// </summary>
public MyBackgroundWorkerClass(System.Threading.SynchronizationContext context)
{
    mContext = context;
}
当从UI线程上的窗体创建worker类时,这是作为同步上下文传递的内容

private void Form1_Load(object sender, EventArgs e)
{
    var worker = new MyBackgroundWorkerClass(SynchronizationContext.Current);
}

如果您能够满足需求,那么后台工作人员很容易实现

定义在后台线程(如保存到数据库)上运行的DoWork方法。当DoWork完成时调用RunWorkerCompleted方法。RunWorkerCompleted在UI线程上运行,您可以毫无问题地更新视图的列表

// on the UI thread
BackgroundWorker worker = new BackgroundWorker();
worker.DoWork += DoWork;
worker.RunWorkerCompleted += RunWorkerCompleted;
worker.RunWorkerAsync("argument");
活动:

static void DoWork(object sender, DoWorkEventArgs e)
{
    e.Result = "4";
}

static void RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    if (e.Error == null)
    {
        string a = (string)e.Result;
        Console.WriteLine(a);
    }
    else
    {
        Console.WriteLine(e.Error.Message);
    }
}

啊,我的糟糕,在类别之间跳跃,我以为这是一个类型问题。这是我以前做的类型问题。我确实在前面尝试过,但它只是在基础上抛出了异常。OnListChanged(e);顺便说一句,只要在UI线程上创建了后台工作者类的实例,这种方法就应该仍然有效(当调用System.Threading.SynchronizationContext.Current时。对我来说,这似乎是一个可行的解决方案。但是,RunWorkerCompleted并没有像预期的那样在主线程上运行。它只是在后台线程上继续运行,我也不知道为什么。我遇到的另一个潜在问题是,c不是我的UI线程创建此线程。我想我可以解决这个问题(我通过直接从主线程创建BackgroundWorker来测试它,但它仍然不起作用)。是的,这成功了。花了很多学员,但我最终得到了它。谢谢!
static void DoWork(object sender, DoWorkEventArgs e)
{
    e.Result = "4";
}

static void RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    if (e.Error == null)
    {
        string a = (string)e.Result;
        Console.WriteLine(a);
    }
    else
    {
        Console.WriteLine(e.Error.Message);
    }
}