问题
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Data.OleDb;
using System.Threading;
namespace SRS
{
public partial class excelimport : Form
{
public excelimport()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
OpenFileDialog openfiledialog1 = new OpenFileDialog();
if (openfiledialog1.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
this.textBox1.Text = openfiledialog1.FileName;
}
}
private void button2_Click(object sender, EventArgs e)
{
if ( backgroundWorker1.IsBusy != true)
{
backgroundWorker1.RunWorkerAsync();
}
}
DataTable mysource;
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker worker = sender as BackgroundWorker;
for (int i = 1; (i <= 10); i++)
{
if ((worker.CancellationPending == true))
{
e.Cancel = true;
break;
}
else
{
string pathconn = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source= " + textBox1.Text + " ;Extended Properties=\"Excel 12.0 Xml;HDR=YES;\";";
OleDbConnection conn = new OleDbConnection(pathconn);
OleDbDataAdapter mydatapter = new OleDbDataAdapter("select * from [" + textBox2.Text + "$]", conn);
DataTable dt = new DataTable();
mydatapter.Fill(dt);
datagridview1.datasource=dt;
System.Threading.Thread.Sleep(500);
worker.ReportProgress((i * 10));
}
}
}
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
this.tbprogress.Text = (e.ProgressPercentage.ToString() + "%");
}
private delegate void tododelegate();
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if ((e.Cancelled == true))
{
this.tbprogress.Text = "Canceled!";
}
else if (!(e.Error == null))
{
this.tbprogress.Text = ("Error: " + e.Error.Message);
}
else
{
this.tbprogress.Text = "Done!";
}
}
private void excelimport_Load(object sender, EventArgs e)
{
}
}
}
I get the error message in line :
datagridview1.datasource=dt;
I tried to alter the code like this :
private DataTable loadingtable()
{
string pathconn = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source= " + textBox1.Text + " ;Extended Properties=\"Excel 12.0 Xml;HDR=YES;\";";
OleDbConnection conn = new OleDbConnection(pathconn);
OleDbDataAdapter mydatapter = new OleDbDataAdapter("select * from [" + textBox2.Text + "$]", conn);
DataTable dt = new DataTable();
mydatapter.Fill(dt);
return dt;
}
and in load event dataGridView1.DataSource = mysource;
and in bw worker mysource =loadingtable();
and then there is no error but then load data takes forever.
回答1:
You can't update UI controls on a non-UI thread.
Try this:
datagridview1.Invoke(() => datagridview1.datasource = dt);
回答2:
You are modifying the GUI from your background worker (which is a no-no) when you do this: datagridview1.datasource=dt;
Have a look for examples that use InvokeRequired
and Invoke
to show how to get some code executed on the event dispatch thread for you.
回答3:
A BackgroundWorker
allows you to run some piece of code in a separate thread from the UI, so you don't lock up the program. The caveat is that the code cannot touch the UI thread directly. You're trying to update a control from the separate thread, so you get an exception.
You've already subscribed to and are using the ProgressChanged
event, so take advantage of it. It runs on the UI thread.
worker.ReportProgress(i * 10, dt);
...
private void backgroundWorker1_ProgressChanged(object sender,
ProgressChangedEventArgs e)
{
this.tbprogress.Text = (e.ProgressPercentage.ToString() + "%");
dataGridView1.DataSource = (DataTable)e.UserState;
}
FYI, you're assigning the DataSource within a loop, so each iterate overwrites the previous DataSource. You probably want to double-check your logic.
Also, you've got syntax errors. It's DataSource
, not datasource
.
来源:https://stackoverflow.com/questions/28597958/invalid-cross-thread-access-backgroundworker-error-c-sharp