如何从backgroundWorker中从外部类调用的方法调用表单上的方法?

时间:2009-08-17 19:12:59

标签: c# visual-studio-2008 class backgroundworker delegates

如何从backgroundWorker中从外部类调用的方法调用表单上的方法?我相信代表们在某种程度上是这个问题的答案,但是在花时间阅读之后,我仍然对这个问题感到困惑。

这是在Visual Studio 2008中, backgroundWorker 从表单运行并调用 ExternalClass.Method 。表单位于名称空间 ProgramName 中, ExternalClass 使用 ProgramName 。当我在windows.form的文件中的名称空间 ProgramName 中声明公共委托 MyDelegate 时,我可以创建一个 MyDelegate 的实例,并在我的表单方法中调用它(但这对我没有帮助),但如果我尝试创建 MyDelegate 的实例并从中调用它我的外部类的方法我无法访问windows.form的方法,即使它是公开的。

感谢

是的,我想从 ExternalClass.Method 中传回进度报告(int percent,string status)。你能解释一下CSharpAtl(或任何人)吗?

4 个答案:

答案 0 :(得分:2)

答案 1 :(得分:1)

要实现的主要是你实际上有两个级别的同步:在Form和BackgroundWorker之间,以及BackgroundWorker和ExternalClass对象之间。

Form异步调用BackgroundWorker.DoWork(),它在另一个线程中运行。对表单的任何更新都应该通过Form.Invoke()(在表单的线程中触发任意委托),或者更好的是,通过BackgroundWorker.ProgressChanged事件(在表单的线程中触发特定事件)。< / p>

所以你要做的是代理从ExternalClass方法返回到BackgroundWorker的状态更新,后者又将它们推送到Form。我过去做过这种方法的一种方法是使用回调委托:

public delegate void ProgressCallback(double percentCompleted, string status);

让我昂贵的worker方法将回调作为参数:

public void ExpensiveMethod(ProgressCallback callback) {
    while(doingThings) {
        if(callback != null) callback(percentDone, statusString);
    }
}

然后在您的BackgroundWorker类中,定义一个与您的回调委托匹配的方法,并让它调用BackgroundWorker.ReportProgress()来触发BackgroundWorker.ProgressChanged事件,这可以反过来更新您的表单状态。

更新:这与Henk Holterman在他的新编辑中提出的解决方案基本相同。

答案 2 :(得分:0)

请注意,你的问题(afaik)不只是关于backgroundwiorker,而是关于如何打破类之间的循环引用。这是标准解决方案的标准问题。

您可以将委托(引用Form方法)与任何对象一起传递给后台工作者。 Bgw可以将它传递给外部方法。委托包括对对象的引用(在本例中为Form)。

请注意,由于您在另一个线程上,因此需要在委托中使用Control.Invoke,或使用Bgw ReportProgress事件。

public partial class Form1 : Form
{
    private void ReportProgresshandler(int percent, string state)
    {
        backgroundWorker1.ReportProgress(percent);  // also does the Invoke
    }

    private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
    {
        var ex = new ExampleClass();
        ex.Dowork(ReportProgresshandler);    
    }
}

等等

class ExampleClass
{
    delegate void ReportDelegate(int percent, string status);

    public void Dowork(ReportDelegate report)
    {
        report(0, "starting");
    }

}

答案 3 :(得分:0)

我不确定是什么问题。而且您也可以使用委托,但不需要委托。

using System.Windows.Forms;
using System.ComponentModel;

public partial class ExampleForm : Form
{

    public ExampleForm()
    {
        InitializeComponent();

        var worker = new BackgroundWorker();
        worker.DoWork += new DoWorkEventHandler(doWork);
        worker.RunWorkerAsync(this);
    }

    void doWork(object sender, DoWorkEventArgs e)
    {
        ExampleForm f = e.Argument as ExampleForm;
        f.Hello();
    }

    private void Hello()
    {

    }

}