跨线程操作无效:RunWorkerCompleted事件应允许更新主表单线程上的datagridview

时间:2019-06-26 21:39:59

标签: c# backgroundworker

尝试从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'是从创建该线程的线程之外的其他线程访问的。

1 个答案:

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