2

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

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

谢谢

是的,我想从ExternalClass.Method传回进度报告(整数百分比,字符串状态) 。你能解释一下那个 CSharpAtl(或任何人)吗?

4

4 回答 4

2

请帮自己一个忙,阅读BackgroundWorker 组件,尤其是“如何:实现使用后台操作的表单”。

其他资源:

于 2009-08-17T19:32:18.473 回答
1

要意识到的主要事情是,您实际上在这里进行了两个级别的同步:Form 和 BackgroundWorker 之间,BackgroundWorker 和 ExternalClass 对象之间。

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

因此,您要做的是将来自 ExternalClass 方法的状态更新代理回 BackgroundWorker,然后将它们推送到 Form。我过去这样做的一种方法是使用回调委托:

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

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

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

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

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

于 2009-08-17T19:43:51.070 回答
0

请注意,您的问题(afaik)不仅与 backgroundwiorker 有关,还与如何打破类之间的循环引用有关。这是标准解决方案的标准问题。

您可以像传递任何对象一样传递委托(指表单方法),也可以传递给 Backgroundworker。Bgw 可以将其传递给外部方法。委托包括对对象的引用(在本例中为表单)。

请注意,由于您在另一个线程上,因此您需要在委托中使用 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");
    }

}
于 2009-08-17T19:27:26.487 回答
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()
    {

    }

}
于 2009-08-17T19:36:15.703 回答