C# 跨线程操作无效:RunWorkerCompleted事件应允许在主窗体线程上更新datagridview

C# 跨线程操作无效:RunWorkerCompleted事件应允许在主窗体线程上更新datagridview,c#,backgroundworker,C#,Backgroundworker,试图从Backgroundworker进程RunWorkerCompleted事件更新datagridview中的行时发生跨线程错误 我有一个单独的类,在这个类中,我在backgroundworker中执行长时间运行的工作,并在完成时尝试从结果更新datagridview。事件激发,但获得交叉异常 尝试在此处更新gridview时失败 DatagHome.Rows[rowIndex]。单元格[AlertInfo]。值=alertMsg.SensorAlert 从阅读numerouos的文章和其他

试图从Backgroundworker进程RunWorkerCompleted事件更新datagridview中的行时发生跨线程错误

我有一个单独的类,在这个类中,我在backgroundworker中执行长时间运行的工作,并在完成时尝试从结果更新datagridview。事件激发,但获得交叉异常

尝试在此处更新gridview时失败 DatagHome.Rows[rowIndex]。单元格[AlertInfo]。值=alertMsg.SensorAlert

从阅读numerouos的文章和其他有问题的文章来看,这应该是可行的,即在backgroundworker完成事件激发后处理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: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,但既然你不显示那段代码,我们就永远不会知道了。