Control 'progressBar1' accessed from a thr

2019-03-06 18:18发布

This question already has an answer here:

I have a method in another dll that gets a lot of data (lopping 22k rows), and I need to create a progress bar for the user.

If I do not call this method asynchronously it hangs the application. But when I call it asynchronously I get the error progressBar1 Control accessed from a thread other than the thread it was created on

private void btnSend_Click(object sender, EventArgs e)
{
    string filePath = tbPath.Text;

    ETLBusiness etlBusiness = new ETLBusiness(filePath);

    Task.Run(() => etlBusiness.LoadData(progressBar1));

}

In that case, backgroundWorker1.RunWorkerAsync is not asynchronous, it is stopping my application in looping

private void btnSend_Click(object sender, EventArgs e)
{
    string filePath = tbPath.Text;

    ETLBusiness etlBusiness = new ETLBusiness(filePath);

    Func<ProgressBar,int> func = etlBusiness.LoadData;

    this.backgroundWorker1.RunWorkerAsync(func(progressBar1));

}

how fixed it?

1条回答
女痞
2楼-- · 2019-03-06 18:58

Your problem is that your control exists on thread A but you are trying to access it via thread B. This is a 'no-no'. Try the following code

private void btnSend_Click(object sender, EventArgs e)
{
    Task.Run(() => LoadData(System.Threading.SynchronizationContext.Current, progressBar1));
}

private void LoadData (System.Threading.SynchronizationContext synchContext, ProgressBar1ObjectType progressBar)
{
    string filePath = tbPath.Text;
    ETLBusiness etlBusiness = new ETLBusiness(filePath);

    synchContext.Post(state => etlBusiness.LoadData(progressBar), null);
}

Where 'ProgressBar1ObjectType' is the Type of progressBar1

Here is another option that may work better:

Thread _myThread = null;
private void btnSend_Click(object sender, EventArgs e)
{
    SynchronizationContext synchContext = SynchronizationContext.Current;
    _myThread = new Thread(() => LoadData(synchContext, progressBar1));

    myThread.Start();

}

private void LoadData (System.Threading.SynchronizationContext synchContext, ProgressBar1ObjectType progressBar)
{
    string filePath = tbPath.Text;
    ETLBusiness etlBusiness = new ETLBusiness(filePath);

    synchContext.Post(state => etlBusiness.LoadData(progressBar), null);
    _myThread.Abort();
}
查看更多
登录 后发表回答