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