C# 跨线程操作无效:RunWorkerCompleted事件应允许在主窗体线程上更新datagridview
试图从Backgroundworker进程RunWorkerCompleted事件更新datagridview中的行时发生跨线程错误 我有一个单独的类,在这个类中,我在backgroundworker中执行长时间运行的工作,并在完成时尝试从结果更新datagridview。事件激发,但获得交叉异常 尝试在此处更新gridview时失败 DatagHome.Rows[rowIndex]。单元格[AlertInfo]。值=alertMsg.SensorAlert 从阅读numerouos的文章和其他有问题的文章来看,这应该是可行的,即在backgroundworker完成事件激发后处理DGV行更新C# 跨线程操作无效:RunWorkerCompleted事件应允许在主窗体线程上更新datagridview,c#,backgroundworker,C#,Backgroundworker,试图从Backgroundworker进程RunWorkerCompleted事件更新datagridview中的行时发生跨线程错误 我有一个单独的类,在这个类中,我在backgroundworker中执行长时间运行的工作,并在完成时尝试从结果更新datagridview。事件激发,但获得交叉异常 尝试在此处更新gridview时失败 DatagHome.Rows[rowIndex]。单元格[AlertInfo]。值=alertMsg.SensorAlert 从阅读numerouos的文章和其他
private void MSbackgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
try
{
string hitfile = (string)e.Argument;
e.Result = _MassSpec.ParseMassFile(hitfile);
}
catch(Exception ex)
{
log.Error("Error in MDShomeForm:MSbackgroundWorker_DoWork - " + e.Result.ToString() + " " + ex.Message + Environment.NewLine);
}
}
private void MSbackgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
// check error, check cancel, then use result
if (e.Error != null)
{
// handle the error
MetroMessageBox.Show(this, "Error in Mass RunWorker = " + e.Error.Message);
}
else if (e.Cancelled)
{
// handle cancellation
MetroMessageBox.Show(this, "Mass RunWorker was Cancelled = " + e.Error.Message);
}
else
{
AlertMsg alertMsg = (AlertMsg)e.Result;
// Test it for hit and update grid in the UI thread
try
{
string searchValue = "";
int rowIndex = -1;
//update the gridview for this sensor
searchValue = alertMsg.SensorType;
foreach (DataGridViewRow row in DataGVhome.Rows)
{
if (row.Cells[2].Value.ToString().Equals(searchValue))
{
rowIndex = row.Index;
break;
}
}
if (rowIndex > -1)
{
// update the L1 Alert for this sensor at rowIndex
DataGVhome.Rows[rowIndex].Cells["AlertInfo"].Value = alertMsg.SensorAlert;
//dataGVhome.Rows[rowIndex].Cells["AlertIndicator"].Value = alertMsg.SensorAlert;
switch (alertMsg.SensorAlertInd)
{
case (int)StandardVals.AlertInds.Green:
DataGVhome.Rows[rowIndex].Cells["AlertIndicator"].Value = "Green";
DataGVhome["AlertIndicator", rowIndex].Style.BackColor = Color.LightGreen;
break;
case (int)StandardVals.AlertInds.Yellow:
DataGVhome.Rows[rowIndex].Cells["AlertIndicator"].Value = "Yellow";
DataGVhome["AlertIndicator", rowIndex].Style.BackColor = Color.Yellow;
break;
case (int)StandardVals.AlertInds.Red:
DataGVhome.Rows[rowIndex].Cells["AlertIndicator"].Value = "Red";
DataGVhome["AlertIndicator", rowIndex].Style.BackColor = Color.Red;
break;
}
DataGVhome.Update();
}
}
catch (Exception ex)
{
log.Error("Error in MDShomeForm:MSBackgroundWorkerCompleted - " + ex.Message + Environment.NewLine);
}
}
// general cleanup code, runs when there was an error or not.
}
我将异常记录在这里
2019-06-26 17:16:18564错误MDS_Command_Application.MDShomeForm-MDShomeForm中的错误:MSBackgroundWorkerCompleted-跨线程操作无效:从创建控件“DatagHome”的线程以外的线程访问控件“DatagHome”。这确实似乎仍然是我正在使用的MS错误,因为它不是允许从runworkercompleted事件更新主UI线程,即使文档说应该这样做。 下面是我如何让它在没有跨线程异常的情况下从此事件更新UI的。浪费了很多时间尝试各种不同的方法,但希望这能有所帮助。必须使用Invoke来绕过此异常。 我还转而在中使用datatable,并希望它能解决相同的问题,直到我做了下面的工作 替换了RunworkerCompleted事件中的else代码,现在一切正常
else
{
AlertMsg alertMsg = e.Result as AlertMsg;
// Don't do anything if the form's handle hasn't been created
// or the form has been disposed.
if (!this.IsHandleCreated || this.IsDisposed) return;
// Invoke an anonymous method on the thread of the form.
this.Invoke((MethodInvoker)delegate
{
this.l1SensorAlertsTableAdapter.Fill(aGE_MDS_DevDataSet3.L1SensorAlerts);
});
}
您100%确定错误来自您向我们显示的代码行之一吗?代码中的其他地方是否存在字符串MDShomeForm:MSBackgroundWorkerCompleted?我通常使用进度事件并将datatable作为状态对象传递给窗体的主线程。您收到的错误是由于交叉线程造成的,因为后台工作是与表单不同的进程。它返回AlartMsg类,这是我用来尝试和更新datagrid的。它返回AlertMsg类,这是我用来尝试和更新datagrid的。返回的类中的数据是正确的。是的,当我运行调试器第一次尝试更新datagrid列时,它抛出异常。只有MSBackgroundWorkerCompleted用于捕获参与竞争的工作人员的事件。非常令人费解,因为我相信如果您使用backgroundworker流程,MS希望我们这样做。谢谢你的关注。我想你是在给一个后台线程分配MSbackgroundWorker_RunWorkerCompleted,但既然你不显示那段代码,我们就永远不会知道了。