2009-08-17 28 views
2

backgroundWorkerの外部クラスから呼び出されたメソッドからフォームのメソッドを呼び出すにはどうすればよいですか?私は、代議員は何とかこの質問に対する答えだと信じていますが、読書時間を過ごした後も、私はまだこの問題を混乱させています。backgroundWorkerの外部クラスから呼び出されたメソッドからフォーム上のメソッドを呼び出すにはどうすればよいですか?

は、Visual Studio 2008で、BackgroundWorkerのフォームから実行するとExternalClass.Methodを呼び出している。これはされています。フォームは名前空間のProgramNameExternalClassであるのProgramNameを使用してです。私は私のwindows.formのファイルに名前空間のProgramNameにMyDelegateパブリックデリゲートを宣言するとき、私はMyDelegateのインスタンスを作成して、私の形の方法でそれを呼び出す(しかし、これは解決しないことができます私がMyDelegateのインスタンスを作成してそれを私の外部クラスのメソッドから呼び出そうとすると、パブリックであってもwindows.formのメソッドにアクセスできません。

おかげで

はい、私は戻ってExternalClass.Methodからの進捗報告(int型パーセント、文字列の状態)を渡したいです。 CSharpAtl(または誰か)についてもう少し説明できますか?

+0

外部クラスが呼び出し側クラスに何かを通知できるようにしますか?そうであれば、呼び出し側クラスがサブスクライブするバックグラウンドワーカークラスにイベントを配置できます。 – CSharpAtl

答えて

0

あなたの質問(afaik)はバックグラウンドワーカーに関するだけでなく、クラス間の循環参照を破る方法についても同様です。これは標準的な解決策の標準的な問題です。

デリゲート(フォームメソッドを参照)を任意のオブジェクトと同様に、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"); 
    } 

} 
+0

Delegate.Invoke()ではなく、* Form *のInvoke()メソッドを使用する必要があります。 – STW

+0

Yoooder:良い点、絶対に。私はReportProgressを使用してそれを回避しました。 –

0

私はトラブルが何であるかわかりません。また、デリゲートを使用することもできますが、デリゲートは必要ありません。フォームとBackgroundWorkerの間、およびBackgroundWorkerのとExternalClassオブジェクト間:

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() 
    { 

    } 

} 
1

実現する主なものは、あなたが実際に同期がここで起こって、2つのレベルを持っているということです。

フォームは、別のスレッドで実行されているBackgroundWorker.DoWork()を非同期に呼び出しています。フォームの更新はForm.Invoke()(フォームのスレッドの任意のデリゲートを呼び出す)またはより良い方法ではBackgroundWorker.ProgressChangedイベント(フォームのスレッド内の特定のイベントを発生させる)を通じて行われます。

代理人ステータスが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.ProgressChangedイベントをトリガーするBackgroundWorker.ReportProgress()イベントを呼び出すと、フォームの状態が更新されます。

アップデート:これは、Henk Holtermanが新しい編集で提案したソリューションと基本的に同じです。

関連する問題