在c#中使用backgroundworker时,跨线程操作无效

时间:2014-08-20 09:41:53

标签: c# multithreading winforms backgroundworker

  private bool ImportData()
        {   
            bool result = false;
         try
            {

                      intdevid = int.Parse(cmbDeviceName.SelectedValue.ToString());
                         FetchDevicedata(intdevid);


                    //FTPTCompletedBatchTransfer();
                    FetchMaxReportId();

                    GetFTPFile(strDeviceIP, strDeviceUsername, strDevicePwd, strDevicePath + "//RunningBatch//RunningBatch.db", "RunningBatch.db"); // Copy RunningBatch.db to Debug Folder from Remote 
                    LoadRunningData(); // Get Running Data in dataset from running.db
                    if (DecodeBatchData_R() == false)
                    {

                        MessageBox.Show("Running Batch Data Not Found");


                    }// save in batch master and row data table

                    GetFTPFile(strDeviceIP, strDeviceUsername, strDevicePwd, strDevicePath + "//CompletedBatch//CompletedBatch.db", "CompletedBatch.db");
                    LoadCompletedData();
                    if (DecodeBatchData() == false)
                    {

                        MessageBox.Show("Completed Batch Data not found");

                    }
                    result = true;

                }



            catch (Exception ex)\\here error:Cross-thread operation not valid: Control 'cmbDeviceName' accessed from a thread other than the thread it was created on.
            {
                clsLogs.LogError("Error: " + ex.Message + this.Name + " || ImportData");
                result = false;

            }



            return result;
        }
    private void btnimport_Click(object sender, EventArgs e)
    {
         //////////////////copy checkweigher .db to database folder
        dsCheckRptId = new DataSet();
        ///////////////////////////////////////////////////////////
        if (cmbDeviceName.Text.ToString().Trim() == "--Select--")
        {
            MessageBox.Show("Please Select Proper Device");
            cmbDeviceName.Focus();
            return;
        }
        var deviceId = (int)cmbDeviceName.SelectedValue;
        bgw.RunWorkerAsync(deviceId);
        progressBar1.Visible = true;
        label2.Visible = true;



    }
    void bgw_DoWork(object sender, DoWorkEventArgs e)
    {

        for (int i = 1; i <= 100; i++)
        {
            var deviceId = (int)e.Argument;
            e.Result = ImportData();
            System.Threading.Thread.Sleep(100);
            bgw.ReportProgress(i);

        }
    } 

    void bgw_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        progressBar1.Value = e.ProgressPercentage;
        label2.Text = String.Format("Progress: {0} %", e.ProgressPercentage);
    }

    void bgw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        var result = (bool)e.Result;
        if (cmbDeviceName.SelectedValue != null && cmbDeviceName.SelectedValue.ToString().Trim() != "0" && cmbDeviceName.SelectedValue.ToString().Trim() != "System.Data.DataRowView" && cmbDeviceName.SelectedValue.ToString().Trim() != "")

          if (result)
        {
            MessageBox.Show("Data Import Completed Successfully for " + strDevicename);
            clsLogs.LogEvent(3, "Data Import Completed Successfully for " + strDevicename);
        }
        else
        {
            MessageBox.Show("Data Import Fail For " + strDevicename);
            clsLogs.LogEvent(3, "Data Import Fail for " + strDevicename);
        }    
        progressBar1.Visible = false;
        label2.Visible = false;
    }

;当我运行这个后台工作程序编码时,会出现一个错误,指出“跨线程操作无效:控制'cmbDeviceName'是从其创建的线程以外的线程访问的。”

如何解决这个问题呢?

1 个答案:

答案 0 :(得分:1)

WinForms控件不是线程安全的,因此控件上的跨线程操作无效。您只能从创建这些控件的线程访问控件。在您的代码中,您正在从后台线程访问cmbDeviceName组合框。解决此问题的最佳方法是将intdevid作为RunWorkerAsync参数传递:

// executed on main thread
var deviceId = (int)cmbDeviceName.SelectedValue;
backgroundWorker.RunWorkerAsync(deviceId);

DoWork处理程序中获取此参数:

private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
   // executed on background thread
   var deviceId = (int)e.Argument;

   // ...
}

建议阅读:Safe, Simple Multithreading in Windows Forms