C# Backgroundworker进度异常

C# Backgroundworker进度异常,c#,progress-bar,backgroundworker,C#,Progress Bar,Backgroundworker,我使用Backgroundworker在将数据导出到excel时显示进度。但执行与线程有关。这是我的密码: public frmPLANNING() { InitializeComponent(); lblStatus.Text = string.Empty; backgroundWorker1.ProgressChanged += new ProgressChangedEventHandler(ba

我使用Backgroundworker在将数据导出到excel时显示进度。但执行与线程有关。这是我的密码:

    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!";
        }
publicfrmplanning()
{
初始化组件();
lblStatus.Text=string.Empty;
backgroundWorker1.ProgressChanged+=新的ProgressChangedEventHandler(backgroundWorker1\u ProgressChanged);
backgroundWorker1.DoWork+=新的DoWorkerVenthandler(backgroundWorker1_DoWork);
backgroundWorker1.RunWorkerCompleted+=新的RunWorkerCompletedEventHandler(backgroundWorker1\U RunWorkerCompleted);
backgroundWorker1.WorkerReportsProgress=true;
progressBar1.最大值=100;
}
私有void tbrExport_单击(对象发送方,事件参数e)
{
if(backgroundWorker1.IsBusy)
{
backgroundWorker1.CancelAsync();
}
其他的
{
progressBar1.值=progressBar1.最小值;
backgroundWorker1.RunWorkerAsync();
}
}
私有void backgroundWorker1\u DoWork(对象发送方,DoWorkEventArgs e)
{            
SqlConnection-cnn;
var ssqltable=“规划”;
字符串sql=null;
字符串数据=null;
var i=0;
var j=0;
Microsoft.Office.Interop.Excel.Application xlApp;
工作手册;
工作表;
对象错误值=缺少.Value;
xlApp=新应用程序();
xlWorkBook=xlApp.Workbooks.Add(错误值);
xlWorkSheet=(工作表)xlWorkBook.Worksheets.get_项(1);
cnn=新的SqlConnection(strConStr);
cnn.Open();
sql=“选择*自”+ssqltable;
var dscmd=新的SqlDataAdapter(sql,cnn);
var ds=新数据集();
dscmd.Fill(ds);
foreach(ds.表中的数据表dt)
{
对于(var i1=0;i1对于(i=0;iExcel自动化要求您以特定方式创建和使用Microsoft.Office.Interop.Excel.Application
和相关对象:

  • 它们必须在最初创建它们的线程中使用,并且
  • 该线程必须是单线程单元(STA)线程
换句话说,您需要像对待UI对象一样对待Excel对象。确保它们是在主UI线程(已经是STA)中创建的,并使用
Control.Invoke()
或类似方法确保访问这些对象的任何代码都在该主UI线程中执行


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

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

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

你能帮我在哪里用代码纠正这个问题吗?它在以下位置引发了错误:if(saveFileDialog1.ShowDialog()==DialogResult.OK)我在您的代码中没有看到任何显示创建
saveFileDialog1
的位置的内容。但是,如果您在主UI线程中创建它,那么它需要保留在那里。它必须遵循与Excel对象相同的规则,即使用
Control.Invoke()
或类似的命令来执行该代码。在我看来,将该代码放在您已有的
RunWorkerCompleted
事件处理程序中是一个合适的位置。我移动了if(saveFileDialog1.ShowDialog()==DialogResult.OK){xl工作簿.SaveAs(savePath);xl工作簿.Close(true,misValue,misValue);xlApp.Quit();releaseObject(xlWorkSheet);releaseObject(xlWorkBook);releaseObject(xlApp);MessageBox.Show(“已创建规划\u EXCEL\u Template.xlsx文件!”);)运行工作完成,问题似乎已解决,但ProgressBar运行2次循环(达到100%时运行2次)。有什么想法吗?缺乏可靠重现问题的良好工具,无法确定问题是什么。但通常情况下,问题的形式为“当使用
BackgroundWorker
时,工作似乎要做两次或更多次”结果是
dowwork
事件被订阅了不止一次(例如,在设计器中,然后再次在代码中,或仅在代码中,但每次执行命令一次,因此每次执行命令时,完成工作的次数增加一次)。上面显示的代码肯定会有该错误。请尝试仅订阅设计器中的所有事件处理程序,或在每次运行该命令时创建一个新的
BackgroundWorker
对象。