2011-11-01 35 views
2

我正在尝试更新主窗体上的进度条,并在不同的类中完成工作。例如:C#,使用不同类别的后台工作人员更新进度栏

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方法,我设置了进度条的最大值和更新值每次的东西转移到在这个方法中的数据库,但是当我这样做时没有任何反应。在数据库中运行存储过程的方法中有代码,但只要它碰到那部分代码,它就停止调试,我必须再次运行该过程。

我在这里做错了什么?我是否需要重写我拥有的所以实际方法是以主要形式存在,而不是在不同的班级中?我是一名初级开发人员(几个月前刚开始),所以如果我正在做一些明显错误的事情,或者我没有足够好地解释这件事,请原谅我。

任何帮助将不胜感激。

+1

不确定这是关于什么,但你一定要排除故障“停止调试”。 BackgroundWorker吞下异常并将它们传递给具有e.Error属性的RunworkerCompleted事件处理程序。一些你不想忽视的东西。最好的方法是不要忽略它,使用Debug + Exceptions,为CLR异常勾选Thrown复选框。 –

回答

2

你不能改变用户界面,除非你在主线程上,而你的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

我认为原因是你得到一个IllegalCrossThreadException,因为你试图从一个不同的线程访问控件,而不是它创建的。 BackgroundWorker提供了一个ReportProgress方法和一个ProgressChanged事件,它通常用于这种更新,并将在UI线程上执行。当访问从另一个线程比UI线程的进度,像这样做:

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

一点题外话:这不是很好的设计的进度传递给你的工人阶级。表格可能会关闭,可能会被处置,工作人员也不会知道任何事情,最终会失败,可能不会被抓到。此外,如果工作人员可能不需要,工作人员依赖于System.Windows.Forms。而是让您的工作人员通过事件报告进度,并将其传递到创建该工作人员的类的进度条上。

+1

另外,如果你有兴趣,[进步](https://github.com/scottrippey/Progression/wiki)(免责声明:我写了它)是一个非常简单的进度计算库,允许你的工作方法正确报告进步,而不知道UI的任何内容。要么UI订阅线程安全事件,要么'BackgroundWorker'可以订阅并报告事件。 –