我使用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。仅当调试器附加到进程时才会引发此异常。
答案 0 :(得分:0)
Excel自动化要求您以特定方式创建和使用Microsoft.Office.Interop.Excel.Application
及相关对象:
换句话说,您需要像处理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);