无效的跨线程访问backgroundworker错误c#
Invalid cross thread access backgroundworker error c#
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)
{
}
}
}
我在行中收到错误消息:
datagridview1.datasource=dt;
我试过这样修改代码:
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;
}
并且在加载事件中 dataGridView1.DataSource = mysource;
并且在 bw worker mysource =loadingtable();
然后没有错误,但是加载数据需要很长时间。
您无法在非 UI 线程上更新 UI 控件。
试试这个:
datagridview1.Invoke(() => datagridview1.datasource = dt);
当您这样做时,您正在从后台工作人员修改 GUI(这是一个禁忌):datagridview1.datasource=dt;
查看使用 InvokeRequired
和 Invoke
的示例,向您展示如何在事件分派线程上执行一些代码。
BackgroundWorker
允许您 运行 在与 UI 不同的线程中执行某些代码,因此您不会锁定程序。需要注意的是代码不能直接接触 UI 线程。您正在尝试从单独的线程更新控件,因此出现异常。
您已经订阅并正在使用 ProgressChanged
活动,所以好好利用它吧。它 运行 在 UI 线程上。
worker.ReportProgress(i * 10, dt);
...
private void backgroundWorker1_ProgressChanged(object sender,
ProgressChangedEventArgs e)
{
this.tbprogress.Text = (e.ProgressPercentage.ToString() + "%");
dataGridView1.DataSource = (DataTable)e.UserState;
}
仅供参考,您是在循环内分配数据源,因此每次迭代都会覆盖之前的数据源。您可能想仔细检查您的逻辑。
此外,您还有语法错误。是 DataSource
,不是 datasource
。
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)
{
}
}
}
我在行中收到错误消息:
datagridview1.datasource=dt;
我试过这样修改代码:
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;
}
并且在加载事件中 dataGridView1.DataSource = mysource;
并且在 bw worker mysource =loadingtable();
然后没有错误,但是加载数据需要很长时间。
您无法在非 UI 线程上更新 UI 控件。
试试这个:
datagridview1.Invoke(() => datagridview1.datasource = dt);
当您这样做时,您正在从后台工作人员修改 GUI(这是一个禁忌):datagridview1.datasource=dt;
查看使用 InvokeRequired
和 Invoke
的示例,向您展示如何在事件分派线程上执行一些代码。
BackgroundWorker
允许您 运行 在与 UI 不同的线程中执行某些代码,因此您不会锁定程序。需要注意的是代码不能直接接触 UI 线程。您正在尝试从单独的线程更新控件,因此出现异常。
您已经订阅并正在使用 ProgressChanged
活动,所以好好利用它吧。它 运行 在 UI 线程上。
worker.ReportProgress(i * 10, dt);
...
private void backgroundWorker1_ProgressChanged(object sender,
ProgressChangedEventArgs e)
{
this.tbprogress.Text = (e.ProgressPercentage.ToString() + "%");
dataGridView1.DataSource = (DataTable)e.UserState;
}
仅供参考,您是在循环内分配数据源,因此每次迭代都会覆盖之前的数据源。您可能想仔细检查您的逻辑。
此外,您还有语法错误。是 DataSource
,不是 datasource
。