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);
}
}