2

backgroundWorker の外部クラスから呼び出されたメソッドからフォームのメソッドを呼び出すにはどうすればよいですか? デリゲートは何とかこの質問に対する答えだと思いますが、時間をかけて読んだ後でも、この問題にまだ混乱しています。

これは Visual Studio 2008 で、backgroundWorkerはフォームから実行され、ExternalClass.Methodを呼び出します。フォームは名前空間 ProgramNameにあり、ExternalClassProgramNameを使用して います。windows.form のファイルの名前空間ProgramNameでパブリック デリゲートMyDelegateを宣言すると、 MyDelegateのインスタンスを作成してフォームのメソッドで呼び出すことができます (ただし、これは役に立ちません)。MyDelegateのインスタンスを作成し、外部クラスのメソッドから呼び出します。公開されているにもかかわらず、windows.form のメソッドにアクセスできません。

ありがとう

はい、 ExternalClass.Methodから進捗レポート (int パーセント、文字列ステータス) を返したいです。その CSharpAtl (または誰か) についてもう少し説明していただけますか?

4

4 に答える 4

1

ここでは、Form と BackgroundWorker の間、および BackgroundWorker と ExternalClass オブジェクトの間で、実際には 2 つのレベルの同期が行われていることに注意してください。

BackgroundWorker.DoWork()フォームは、別のスレッドで実行されている を非同期的に呼び出しています。フォームへの更新はすべてForm.Invoke()(フォームのスレッドで任意のデリゲートを起動する) か、BackgroundWorker.ProgressChangedイベント (フォームのスレッドで特定のイベントを起動する) を介して行われる必要があります。

したがって、ExternalClass メソッドからのステータス更新を BackgroundWorker にプロキシし、BackgroundWorker がそれらを Form にプッシュします。過去にこれを行った 1 つの方法は、コールバック デリゲートを使用することです。

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ます。これにより、フォームの状態を更新できます。

更新: これは基本的に Henk Holterman が新しい編集で提案した解決策と同じです。

于 2009-08-17T19:43:51.070 に答える
0

あなたの質問(afaik)は、backgroundwiorkerだけでなく、クラス間の循環参照を壊す方法についても同じであることに注意してください。これは、標準ソリューションの標準的な問題です。

デリゲート(Formメソッドを参照)を他のオブジェクトと同じように、Backgroundworkerにも渡すことができます。そして、Bgwはそれを外部メソッドに渡すことができます。デリゲートには、オブジェクト(この場合はフォーム)への参照が含まれます。

別のスレッドを使用しているため、デリゲート内でControl.Invokeを使用するか、BgwReportProgressイベントを使用する必要があることに注意してください。

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 に答える