交叉线程操作在BackgroundWorker中无效 [英] Cross thread operation not valid in BackgroundWorker

查看:122
本文介绍了交叉线程操作在BackgroundWorker中无效的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在数据gridview中显示一些表单加载的数据,我想显示的数据是大量的行,当我使用后台工作进程显示我以下错误。



我的代码:

  private void backgroundWorker1_DoWork(object sender,DoWorkEventArgs e)
{
try
{
FTPUtility obj = new FTPUtility();
dataGridViewRequest.DataSource = obj.ListRequestFiles();
dataGridViewRequest.Columns [0] .AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
dataGridViewRequest.Columns [1] .AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
dataGridViewRequest.Columns [2] .AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;

dataGridViewResponses.DataSource = obj.ListResponseFiles();
dataGridViewResponses.Columns [0] .AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
dataGridViewResponses.Columns [1] .AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
dataGridViewResponses.Columns [2] .AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;

}
catch(Exception ex)
{

MessageBox.Show(ex.Message,Error Message,MessageBoxButtons.OK,MessageBoxIcon。错误);
}
}

表单载入:

  private void FormFTP_Load(object sender,EventArgs e)
{
try
{

/ /this.comboBoxRequests.SelectedIndex = 0;
backgroundWorker1.RunWorkerAsync();

}
catch(Exception ex)
{

MessageBox.Show(ex.Message,Error Message,MessageBoxButtons.OK,MessageBoxIcon。错误);
}
}


解决方案



例如,您可以加载您的数据,如下所示:

  private async void Form_Load(object sender,EventArgs e)
{
//做一些初始化
await LoadData();
//做一些你需要执行的其他初始化。
}

private async任务LoadData()
{
//在此处加载您的数据
//例如
FTPUtility obj = new FTPUtility();
dataGridViewRequest.DataSource = obj.ListRequestFiles();
}

这样当运行表单时,命令按照你写的顺序运行该UI是响应式的,你不会面对使用 BackgroundWorker 或线程如跨线程操作异常的常见困难。



关键点在于使用async / await。有关详细信息,请参阅使用Async和Await进行异步编程



记住这一点,你想调用LoadData的地方,你应该这样调用:

  await LoadData(); 

您在写这段代码的方法应该是async:

  private async void RefreshButton_Click(object sender,EventArgs e)
{
await LoadData
}

EDIT For .Net 4.0




对于.Net 4.0,您可以使用 Task.Run BackgroundWorker 。我建议 Task.Run ,因为它更简单,更易读。



请注意,Cross Thread Operation Exception会抛出当您从UI之外的另一个线程访问UI元素。在这种情况下,你应该使用 this.Invoke(new Action(()=> {/ * Access UI Here * /}));




BackgroundWorker方法

  private void Form1_Load(object sender,EventArgs e)
{
backgroundWorker1.RunWorkerAsync();
//如果你把一些代码放在这里例如MessageBox.Show();
//代码将自动运行,不要等待worker完成任务。
}

private void backgroundWorker1_DoWork(object sender,DoWorkEventArgs e)
{
this.LoadData();
}

public void LoadData()
{
var ftp = new FtpUtility();
var data = ftp.ListRequestFiles();
this.Invoke(new Action(()=>
{
//设置列和其他UI东西
//设置网格数据源
this.dataGridView1 .DataSource = data;
}));
}




  • 记住您以前使用过的所有地方 LoadData ,现在应该使用 backgroundWorker1.RunWorkerAsync();

  • 在工作者完成任务后执行作业,将您的作业放在 backgroundWorker1_RunWorkerCompleted 中调用部分 LoadData



Task.Run方法

  private void Form1_Load(object sender,EventArgs e)
{
Task.Run(()=>
{
LoadData();
})
.ContinueWith(x =>
{
//你可以放置你想要在LoadData完成后运行的代码
//如果你在这里访问UI,你应该使用Invoke
});
//如果你把一些代码放在这里例如MessageBox.Show();
//代码将自动运行,不要等待worker完成任务。
}

public void LoadData()
{
var ftp = new FtpUtility();
var data = ftp.ListRequestFiles();
this.Invoke(new Action(()=>
{
//设置列和其他UI东西
//设置网格数据源
this.dataGridView1 .DataSource = data;
}));
}




  • 记住您以前使用过的所有地方 LoadData ,现在你应该使用 Task.Run(()=> {LoadData();}); >
  • 如果您想在 LoadData 完成后执行作业,请将作业放在 ContinueWith 调用部分 LoadData


I want to display some data on form load in a data gridview , the data which i want to display is in large number of rows , when i use background worker processor it show me the following error.

My code:

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
    try
    {
        FTPUtility obj = new FTPUtility();
        dataGridViewRequest.DataSource = obj.ListRequestFiles();
        dataGridViewRequest.Columns[0].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
        dataGridViewRequest.Columns[1].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
        dataGridViewRequest.Columns[2].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;

        dataGridViewResponses.DataSource = obj.ListResponseFiles();
        dataGridViewResponses.Columns[0].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
        dataGridViewResponses.Columns[1].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
        dataGridViewResponses.Columns[2].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;

    }
    catch (Exception ex)
    {

        MessageBox.Show(ex.Message, "Error Message", MessageBoxButtons.OK, MessageBoxIcon.Error);
    }
}

Form load:

private void FormFTP_Load(object sender, EventArgs e)
{
    try
    {

        //this.comboBoxRequests.SelectedIndex = 0;
        backgroundWorker1.RunWorkerAsync();

    }
    catch (Exception ex)
    {

        MessageBox.Show(ex.Message, "Error Message", MessageBoxButtons.OK, MessageBoxIcon.Error);
    }
}

解决方案

There are many different ways to prevent the form from being freezed.
For example you can load your data like this:

private async void Form_Load(object sender, EventArgs e)
{
    //do some initializations
    await LoadData();
    //do some other initializations that you need to perform.
}

private async Task LoadData()
{
    //Load your data here
    //For example
    FTPUtility obj = new FTPUtility();
    dataGridViewRequest.DataSource = obj.ListRequestFiles();
}

This way when running the form, the commands run in the sequence you wrote while the UI is responsive and you will not face with common difficulties of using BackgroundWorker or threads like Cross thread operation exceptions.

The key point is in using async/await. For more information read Asynchronous Programming with Async and Await

Remember that this way, every where you want to call LoadData, you should call it this way:

await LoadData();

And the method that you write this code in, should be async:

private async void RefreshButton_Click(object sender, EventArgs e)
{
    await LoadData();
}

EDIT For .Net 4.0


For .Net 4.0 you can use both Task.Run or BackgroundWorker. I recommend Task.Run because it is more simple and more readable.

Please note Cross Thread Operation Exception will throw when you access the UI elements from another thread than UI. In this situations you should use this.Invoke(new Action(()=>{/*Access UI Here*/})); instead. And never put a time-consuming task in your invoke part.

BackgroundWorker Approach:

private void Form1_Load(object sender, EventArgs e)
{
    backgroundWorker1.RunWorkerAsync();
    //If you put some code here for example MessageBox.Show(""); 
    //The code will immadiately run and don't wait for worker to complete the task.
}

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
    this.LoadData();
}

public void LoadData()
{
    var ftp = new FtpUtility();
    var data = ftp.ListRequestFiles();
    this.Invoke(new Action(() =>
    {
        //Setup columns and other UI stuff
        //Set datasource of grid
        this.dataGridView1.DataSource = data;
    }));
}

  • Remember everywhere you formerly used LoadData, now you should use backgroundWorker1.RunWorkerAsync(); instead.
  • If you want to do a job after the worker completes the task, put your job in backgroundWorker1_RunWorkerCompleted or in Invoke part of LoadData.

Task.Run Approach

private void Form1_Load(object sender, EventArgs e)
{
    Task.Run(() =>
    {
        LoadData();
    })
    .ContinueWith(x =>
    {
        //You can put codes you want run after LoadData completed here
        //If you access the UI here, you should use Invoke
    });
    //If you put some code here for example MessageBox.Show(""); 
    //The code will immadiately run and don't wait for worker to complete the task.
}

public void LoadData()
{
    var ftp = new FtpUtility();
    var data = ftp.ListRequestFiles();
    this.Invoke(new Action(() =>
    {
        //Setup columns and other UI stuff
        //Set datasource of grid
        this.dataGridView1.DataSource = data;
    }));
}

  • Remember everywhere you formerly used LoadData, now you should use Task.Run(()=>{LoadData();}); instead.
  • If you want to do a job after the LoadData completes, put your job in ContinueWith or in Invoke part of LoadData.

这篇关于交叉线程操作在BackgroundWorker中无效的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆