背景工作进展的例外

时间:2017-05-24 04:12:22

标签: c# progress-bar backgroundworker

我使用Backgroundworker显示将数据导出到Excel时的进度。但是exeption与Thread有关。这是我的代码:

    public frmPLANNING()
        {
            InitializeComponent();
            lblStatus.Text = string.Empty;
            backgroundWorker1.ProgressChanged += new ProgressChangedEventHandler(backgroundWorker1_ProgressChanged);
            backgroundWorker1.DoWork += new DoWorkEventHandler(backgroundWorker1_DoWork);
            backgroundWorker1.RunWorkerCompleted += new RunWorkerCompletedEventHandler(backgroundWorker1_RunWorkerCompleted);
            backgroundWorker1.WorkerReportsProgress = true;
            progressBar1.Maximum = 100;
        }
private void tbrExport_Click(object sender, EventArgs e)
        {
            if (backgroundWorker1.IsBusy)
            {
                backgroundWorker1.CancelAsync();
            }
            else
            {
                progressBar1.Value = progressBar1.Minimum;

                backgroundWorker1.RunWorkerAsync();
            }
        }
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {            
            SqlConnection cnn;
            var ssqltable = "PLANNING";
            string sql = null;
            string data = null;
            var i = 0;
            var j = 0;
            Microsoft.Office.Interop.Excel.Application xlApp;
            Workbook xlWorkBook;
            Worksheet xlWorkSheet;
            object misValue = Missing.Value;
            xlApp = new Application();
            xlWorkBook = xlApp.Workbooks.Add(misValue);
            xlWorkSheet = (Worksheet)xlWorkBook.Worksheets.get_Item(1);
            cnn = new SqlConnection(strConStr);
            cnn.Open();
            sql = "SELECT * From " + ssqltable;
            var dscmd = new SqlDataAdapter(sql, cnn);
            var ds = new DataSet();
            dscmd.Fill(ds);           
                foreach (DataTable dt in ds.Tables)
                {
                    for (var i1 = 0; i1 < dt.Columns.Count; i1++)
                    {
                        xlWorkSheet.Cells[1, i1 + 1] = dt.Columns[i1].ColumnName;
                    }
                }
                for (i = 0; i <= ds.Tables[0].Rows.Count - 1; i++)
                {                   
                    var s = i + 1;

                    for (j = 0; j <= ds.Tables[0].Columns.Count - 1; j++)
                    {
                        data = ds.Tables[0].Rows[i].ItemArray[j].ToString();
                        xlWorkSheet.Cells[s + 1, j + 1].EntireColumn.NumberFormat = "@";

                        xlWorkSheet.Cells[s + 1, j + 1] = data;
                        var _totalProgress = ds.Tables[0].Rows.Count-1;

                        backgroundWorker1.ReportProgress(i * 100 / _totalProgress);
                    }
                    Thread.Sleep(100);  
            }                      
            if (saveFileDialog1.ShowDialog() == DialogResult.OK)
            {
                xlWorkBook.SaveAs(savePath);
                xlWorkBook.Close(true, misValue, misValue);
                xlApp.Quit();
                releaseObject(xlWorkSheet);
                releaseObject(xlWorkBook);
                releaseObject(xlApp);              
                MessageBox.Show("PLANNING_EXCEL_Template.xlsx  file has been created!");
            }
        }

        private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            if (!backgroundWorker1.CancellationPending)
            {
                lblStatus.Text = e.ProgressPercentage + "%";
                progressBar1.Value = e.ProgressPercentage;
            }
        }

        private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {           
            lblStatus.Text = "Task completed!";
        }

这是例外:

  

类型&#39; System.Threading.ThreadStateException&#39;的例外情况发生在System.Windows.Forms.dll中但未在用户代码中处理

附加信息:在进行OLE调用之前,必须将当前线程设置为单线程单元(STA)模式。确保您的Main函数标记了STAThreadAttribute。仅当调试器附加到进程时才会引发此异常。

2 个答案:

答案 0 :(得分:0)

Excel自动化要求您以特定方式创建和使用Microsoft.Office.Interop.Excel.Application及相关对象:

  • 必须在最初创建它们的线程中使用它们
  • 该线程必须是单线程单元(STA)线程。

换句话说,您需要像处理UI对象一样处理Excel对象。确保它们是在主UI线程(已经是STA)中创建的,并使用Control.Invoke()或类似物来确保访问这些对象的任何代码都在该主UI线程中执行。

您仍然可以使用BackgroundWorker或您喜欢的任何工作线程范例来处理SQL查询。但是您需要确保将结果传递给在主UI线程上调用的委托,然后可以将它们复制到Excel数据对象中。

答案 1 :(得分:0)

我发现了问题。只需删除:

 backgroundWorker1.DoWork += new DoWorkEventHandler(backgroundWorker1_DoWork);
            backgroundWorker1.RunWorkerCompleted += new RunWorkerCompletedEventHandler(backgroundWorker1_RunWorkerCompleted);