我正在处理使用BackgroundWorker Thread
的应用程序。我有一个按钮点击事件,我正在做一些事情
btnLocate_Click(Object sender, EventArgs e)
{
BackgroundWorker bw = new BackgroundWorker();
bw.DoWork += bw_DoWork;
bw.RunWorkerCompleted += bw_RunWorkerCompleted;
bw.RunWorkerAsync(lstNumbers.CheckedItems[0].ToString());
}
在Background Worker do work事件中,我在全局定义的ObservableCollection
中添加了一些像这样的值
private void bw_DoWork(object sender, DoWorkEventArgs e)
{
try
{
lock (locker)
{
_RecData.Add(new RecNumberData
{
// Some Values
});
}
}
在BackgroundWorker完成事件中,我将此集合设置为网格的数据源,并启动创建新BackgroundWorker
的计时器并再次执行相同的工作。
private void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
grid.DataSource = RecData;
timer1.Start();
}
private void timer1_Tick(object sender, EventArgs e)
{
timer1.Stop();
BackgroundWorker bw = new BackgroundWorker();
bw.DoWork += bw_DoWork;
bw.RunWorkerCompleted += bw_RunWorkerCompleted;
bw.RunWorkerAsync(lstNumbers.CheckedItems[0].ToString());
}
现在,第一次BackgroundWorker
运行时代码运行正常。但是当第二次在Timer滴答事件之后运行时,异常在Cross Thread Opeartion Detected
行引发。
_RecData.Add(new RecNumberData
{
// Some Values
});
可能是什么原因?
答案 0 :(得分:3)
没有看到更多代码的猜测,但我怀疑:
第一次向集合中添加值时,集合未绑定到UI =>没问题
第二次通过它绑定到UI(在第一个完整的事件中),因此您的后台工作者正在尝试更新UI。
解决方案可能是为您的第二个BackgroundWorker创建第二个可观察集合。或者推迟将结果添加到集合中,直到完成事件。
答案 1 :(得分:2)
您正在从GUI线程外部修改GUI对象。你不应该这样做。
通过将RecData
设置为GUI对象的数据源,对RecData的每次更改都将触发将更改GUI对象的通知。绑定RecData
后,您正在从后台工作线程更改RecData
,从而更改您的GUI对象。数据绑定到GUI对象的对象不得被GUI线程以外的任何线程修改。
您可以使用Control.BeginInvoke在GUI线程上排队操作。
答案 2 :(得分:0)
您正在将数据添加到用作图形组件(网格)的数据源的变量中,您需要告诉我们您正在使用的UI技术(WPF?WInform?)。
正在发生的事情是你在一个不是运行UI的线程上做某事,并且大多数UI技术不允许影响它们的事情在另一个线程上运行,有一些机制可以解决这个问题但是它们取决于技术。
大多数情况下,您需要注册更改UI读取的数据的代码以在调度程序上运行(一旦可用,它将排队并在主线程上运行)