C#,使用来自不同类的后台工作程序更新进度条

时间:2011-11-01 23:37:53

标签: c# backgroundworker

我正在尝试更新主窗体上的进度条,其中的工作是在另一个类中完成的。例如:

private void transfer_Click(object sender, EventArgs e)
{
    Guid aspnetUserId = Guid.Parse(System.Configuration.ConfigurationSettings.AppSettings["ASPNetUserID"]);
    WC1toWC2Transfer transfer = new WC1toWC2Transfer(aspnetUserId);

    backgroundWorker1.RunWorkerAsync(transfer);  
}

然后在后台方法中实际调用方法:

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
    WC1toWC2Transfer transfer = e.Argument as WC1toWC2Transfer;
    transfer.WC1ToWC2EmployerTransfer(log, wc1ConnStr, wc2ConnStr, progressBar1);
}

在WC1ToWC2EmployerTransfer方法中,我将进度条设置为最大值,并在每次使用此方法将数据传输到数据库时更新值,但是当我这样做时,没有任何反应。方法中的代码在数据库中运行存储过程,但是一旦它到达代码的那部分,它就会停止调试,我必须再次运行该过程。

我在这里做错了吗?我是否需要重写我所拥有的内容,因此实际的方法是在主窗体中而不是在不同的类中?我是一名初级开发人员(几个月前刚刚开始),如果我做了一些明显的错误,或者我没有充分解释这一点,请原谅我。

非常感谢任何帮助。

2 个答案:

答案 0 :(得分:2)

除非您在主线程上,否则您无法更改UI,而BackgroundWorker将不会这样做。

您需要做的是在主窗体中创建一个事件处理程序来处理backgroundworker的ProgressChanged事件。

例如

// this method should be in your main form.
private void backgroundworker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    // update your progress bar here.
}

在后台工作程序中,调用ReportProgress方法,该方法将触发ProgressChanged事件。

有一个很好的例子here

答案 1 :(得分:1)

我认为原因是你得到IllegalCrossThreadException,因为你试图从不同的线程访问控件而不是创建它。 BackgroundWorker提供了一个ReportProgress方法和一个ProgressChanged事件,该事件通常用于此类更新,并将在UI线程上执行。从UI线程以外的其他线程访问进度条时,请执行以下操作:

if(progressBar1.InvokeRequired) {
  progressBar1.Invoke(new MethodInvoker(delegate { progressBar1.Maximum = someValue; }));
}

作为旁注:将进度条传递给工人类并不是一个很好的设计。表格可以关闭,它可以被处理掉,工人也不会知道任何关于它的事情,最终失败的是ObjectDisposedException可能没有被抓住。此外,当您可能不需要时,您正在使工作人员依赖于System.Windows.Forms。而是让您的工作人员通过事件报告进度,并将其从创建工作者的类传递到您的进度条。