如何从类内向BackgroundWorker报告进度?

13

我的WinForm调用了一个类来执行一些复制操作。我想在窗体上显示这个过程的进度。

我想使用Backgroundworker,但是我不知道如何从类向窗体(/backgroundworker)报告进度。

4个回答

14

使用BackgroundWorkerOnProgressChanged()方法来报告进度,并订阅ProgessChangedEvent以更新GUI中的进度。

您的复制类了解BackgroundWorker并订阅ProgressChanged。它还公开一个自己的ProgressChanged事件,该事件由后台工作者的ProgressChanged事件的事件处理程序引发。最后,您的Form订阅复制类的ProgressChanged事件并显示进度。

代码:

public class CopySomethingAsync
{
    private BackgroundWorker _BackgroundWorker;
    public event ProgressChangedEventHandler ProgressChanged;

    public CopySomethingAsync()
    {
        // [...] create background worker, subscribe DoWork and RunWorkerCompleted
        _BackgroundWorker.ProgressChanged += HandleProgressChanged;
    }

    private void HandleProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        if (ProgressChanged != null)
            ProgressChanged.Invoke(this, e);
    }
}

在您的表单中,只需订阅CopySomethingAsyncProgressChanged事件并显示进度即可。

你会如何将 ProgressChanged 事件暴露给窗体? - Martijn
这是一个非常棒且绝对有帮助的答案,非常感谢! - Christian Casutt

8
关于BackgroundWorker的所有内容都在msdn上,详见此处
正如文章所述:
要接收进度更新通知,请处理ProgressChanged事件。
更新:
阅读Martijn的补充问题后,考虑到他有一个类一直在前台线程上工作,我补充以下内容:
1.工作者类负责工作,因此也负责报告其进度。它生成一个后台线程来执行工作并不关心窗体。
2.因此,我倾向于让该类设置BGW,并处理其ProgressChanged事件,然后引发自己的事件(在前台线程上),窗体本身可以订阅这些事件。我使用这种技术进行大量WinForms编码,效果很好。
另一种选择是将BGW公开为工作者类的公共属性,并直接由窗体处理其事件。但我不太喜欢这样做,因为它使窗体依赖于工作者类的实现。这通常是不好的。

所以我必须在我的类中添加一个公共背景属性,而表单必须注册到ProgressChanged事件? - Martijn

2

我的表单如何订阅自己的ProgressChanged事件? - Martijn
backgroundWorker1.ProgressChanged += new ProgressChangedEventHandler(backgroundWorker1_ProgressChanged); 其中 backgroundWorker1_ProgressChanged 是您的事件处理方法的名称,由委托 ProgressChangedEventHandler 原型化。 - Andreas
不好意思,我不明白。我仍然看不到我的表格如何注册到 ProgressChanged 事件。在您的情况下,有一个处理该事件的方法(backgroundWorker1_ProgressChanged)。但是我的表单需要处理该事件,而不是我的类。 - Martijn
“my class”是什么意思?一个窗体通常由派生类表示。您不需要从BackgroundWorker派生自己的类。可以给我们展示一些代码吗? - Andreas

1

在你的类中调用

 backgroundWorker.ReportProgress(i++);

在表单处理程序中的一个事件

//declare progressBar1 in the form and set range 
// progressBar1.Minimum = 0;
//progressBar1.Maximum = 100;
 private void backgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
       //show progress bar

    }

在这种情况下,我该如何在我的类中公开ProgressChanged事件? - Martijn
我会给你的类添加一个事件,每当BackgroundWorker的ProgressChanged事件被触发时,它也会被触发。你的事件将具有与BackgroundWorker相同的签名。 - andyp
你可以从传递的 ProgressChangedEventArgs 中的 ProgressPercentage 实例字段获取传递给 ReportProgress 的值,即 progressBar1.Value = e.ProgressPercentage; - Andreas
@Martijn,您需要将BackgroundWorker引用设置到您的类中,才能调用Reportprogress方法。 - Arseny

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接