尝试从Backgroundworker进程RunWorkerCompleted事件更新datagridview中的行时遇到跨线程错误。
我有一个单独的类,其中我在backgroundworker中进行长期运行,并且在完成尝试从结果中更新datagridview时。事件触发但出现跨界异常。
当我尝试在此处更新gridview时失败 DataGVhome.Rows [rowIndex] .Cells [“ AlertInfo”]。Value = alertMsg.SensorAlert;
通过阅读numerouos文章和其他有问题的文章,这应该可以工作,即,一旦背景工作人员完成事件触发,就处理DGV行更新。
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:18,564错误MDS_Command_Application.MDShomeForm-MDShomeForm中的错误:MSBackgroundWorkerCompleted-跨线程操作无效:控制'DataGVhome'是从创建该线程的线程之外的其他线程访问的。
答案 0 :(得分:-1)
这确实确实仍然是一个MS错误(我正在使用VS 2017社区FYI),因为即使文档认为应该这样做,它也不允许从runworkercompleted事件更新主UI线程。 以下是我如何获取它来从此事件更新UI而不发生跨线程异常的情况。浪费了很多时间尝试各种不同的方式,但希望这会有所帮助。必须使用Invoke绕过此异常。 我也转而使用数据表,并希望它能解决但仍存在相同的问题,直到执行以下操作为止。
在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);
});
}