2012-01-10 3 views
3

delgatesをパラメータとして渡してイベントの登録を解除しようとしているときに、それらをアンフックする関数が正確にアンフックされていません。Windowsのbackgroundworkerのイベントをアンフックできませんフォーム(C#)

public void registerHandlers(RunWorkerCompleted backgroundWorker1_RunWorkerCompleted, DoWork backgroundWorker1_dowork, ProgressChanged backgroundWorker1_ProgressChanged) 
    { 
     this.backgroundWorker1.RunWorkerCompleted += backgroundWorker1_RunWorkerCompleted; 
     this.backgroundWorker1.DoWork += backgroundWorker1_dowork; 
     this.backgroundWorker1.ProgressChanged += backgroundWorker1_ProgressChanged; 
    } 

    public void unregisterHandlers(RunWorkerCompleted backgroundWorker1_RunWorkerCompleted, DoWork backgroundWorker1_dowork, ProgressChanged backgroundWorker1_ProgressChanged) 
    { 
     this.backgroundWorker1.RunWorkerCompleted -= backgroundWorker1_RunWorkerCompleted; 
     this.backgroundWorker1.DoWork -= backgroundWorker1_dowork; 
     this.backgroundWorker1.ProgressChanged -= backgroundWorker1_ProgressChanged; 
    } 

    private void buuton1_click(object sender, EventArgs e) 
    { 
     registerHandlers(this.worker1_RunWorkerCompleted, this.worker1_doWork, this.worker1_progressChangedHandler); 
     this.backgroundWorker1.RunWorkerAsync(); 
    } 

    private void buuton2_click(object sender, EventArgs e) 
    { 
     registerHandlers(this.worker2_RunWorkerCompleted, this.worker2_doWork, this.worker2_progressChangedHandler); 
     this.backgroundWorker1.RunWorkerAsync(); 
    } 

    // .. 

    private void worker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
    { 
     try 
     { 
      // ... 
     } 
     catch(Exception e) 
     { 
      // .. 
     } 
     finally 
     { 
      unregisterHandlers(this.worker1_RunWorkerCompleted, this.worker1_doWork, this.worker1_progressChangedHandler);  
     } 
    } 

答えて

0

のBackgroundWorkerクラスから継承し、その上にIDisposableインターフェイスを実装し...とのDisposeで登録解除イベント()メソッド..

よろしくを試してみてください。

+0

私はバックグラウンドワーカーを処分しておらず、イベントハンドラを登録および登録解除してコンポーネントを再利用しています。 – user186246

1

これは、新しいデリゲートをインスタンス化して削除しようとしているためです。しかし、その代理人は、最初にイベントに追加されませんでした。フック/アンフックしたいイベントで作業するときは、メソッド自体を使用します。

// ... 

// Hook up to event 
this.backgroundWorker1.RunWorkerCompleted += backgroundWorker1_RunWorkerCompleted; 

// ... 

private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
{ 
    // Unhook from event 
    this.backgroundWorker1.RunWorkerCompleted -= backgroundWorker1_RunWorkerCompleted; 

    // ... 
} 

注:委任することで、私はあなたのイベントハンドラのインスタンス化(すなわちnew RunWorkerCompletedEventHandler(...))を参照していますので、あなたのケースでは、私のような何かをするだろう。

+0

それでもうまくいきませんでした。 – user186246

+0

"did not work"を定義してください。イベントハンドラが呼び出された後に*呼び出されることを意味しますか? –

+0

はい。それは解かれなかった。 – user186246

1

私はこれに別の答えを加えることにしました。以前の投稿のコメントストリームがかなり長くなっていて、現在の回答を編集するとあまりにも長くなりすぎるためです。

私は少しあなたのコードで混乱しています - あなたは元の投稿以来それを変更したかどうかはわかりません。

  1. あなたに/あなたがデリゲートにnewを呼び出さないイベントからイベントハンドラをアンフック/フックされたときに確認してください:私が問題に言いたいことがいくつかのポイントがあります。上記の答えに記載されているように、メソッドの名前を使用してください(以下を参照)。

  2. 他の場所でregisterHandlers(...)unregisterHandlers(...)を使用していない場合、特にそのメソッドがその代理人と同じクラスにある場合は、代理人を渡す必要はありません。確かに、方法は、は、それらの代理人を知ってそれに応じて追加/削除することができます。

  3. 元々は、backgroundWorker1_RunWorkerCompletedというメソッドは、イベントからフックした後であっても、複数回実行されていました。あなたが編集したコードで見ることができるところから、そのイベントハンドラをどこからでも外しているわけではないので、それはまったくもっともらしいです。代わりに、ハンドラのフックを外していますworkerCompleted。また、実際のメソッドと同じようにRunWorkerCompleted代理人のローカル変数(unregisterHandlers(...))の名​​前を付けたということは、コンパイラの混乱の原因になる可能性があります(私はこれは確かではありませんが、

ので、これらの点を考慮して、私はもっとこのような何かに上記のコードを変更します:メソッドと変数の名前は正確にあなた自身と一致しないことを

private BackgroundWorker mBackgroundWorker; // Instantiated elsewhere 

#region Registration 

private void RegisterHandlers() 
{ 
    // Hook up to the background worker events 
    mBackgroundWorker.RunWorkerCompleted += mBackgroundWorker_RunWorkerCompleted; 
    mBackgroundWorker.DoWork += mBackgroundWorker_DoWork; 
    mBackgroundWorker.ProgressChanged += mBackgroundWorker_ProgressChanged; 
} 

private void UnregisterHandlers() 
{ 
    // Unhook from the background worker events 
    mBackgroundWorker.RunWorkerCompleted -= mBackgroundWorker_RunWorkerCompleted; 
    mBackgroundWorker.DoWork -= mBackgroundWorker_DoWork; 
    mBackgroundWorker.ProgressChanged -= mBackgroundWorker_ProgressChanged; 
} 

#endregion 

#region Event Handlers 

private void Button1_Click(object sender, EventArgs e) 
{ 
    RegisterHandlers(); 

    // Start the background worker 
    mBackgroundWorker.RunWorkerAsync(); 
} 

private void mBackgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
{ 
    try 
    { 
     // ... 
    } 
    finally 
    { 
     UnregisterHandlers(); 
    } 
} 

private void mBackgroundWorker_DoWork(object sender, DoWorkEventArgs e) 
{ 
    // ... 
} 

private void mBackgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e) 
{ 
    // ... 
} 

#endregion 

注ので、それに応じて変更するように注意する必要があります。しかし、コードの記述方法に細心の注意を払うと、イベントハンドラのフック/アンフックに関する意味を知ることができます。

これが役に立ちます。私は手動であなたの問題をテストするために小さなテストアプリケーションを書いて、私が作ったポイントを以下している

EDITは、これまでのところ、私は何の問題もありません。テストアプリケーションのソースコードはPasteBinにあります。 Visual Studioでの私の出力ウィンドウに印刷された結果は以下のとおりです。

Worker 1: Do Work 
Worker 1: Run Worker Completed 
Worker 2: Do Work 
Worker 2: Run Worker Completed 
Worker 1: Do Work 
Worker 1: Run Worker Completed 
Worker 2: Do Work 
Worker 2: Run Worker Completed 

上記の出力が連続して労働者のボタンをクリックした結果として、次のとおりです。ワーカー1、労働者2、労働者1、作業員2

EDIT 2

デザイナーのイベントハンドラーを制御しようとすると、BackgroundWorkerが生成されます。

  1. WinFormsデザイナー生成コードbackgroundWorker1をインスタンス化すると思います。
  2. WinFormsデザイナー生成コードは、イベントハンドラーをbackgroundWorker1(ハンドラーカウント:1)にフックします。
  3. ユーザーはbutton1をクリックします。
  4. コードでは、イベントハンドラをbackgroundWorker1(ハンドラカウント:2)にフックします。 これは、複数のフックアップを取得する場所です。

このは何が起こっているかある場合は、フォームデザイナのプロパティグリッドのイベント一部に指定された任意のイベントハンドラを削除することによってイベントにフックからデザイナーで生成されたコードを停止することができるはずです。

+0

状況に応じてイベントハンドラを変更したいので、registerHandlers()メソッドとunregisterHandlers()メソッドにパラメータを追加しました。 – user186246

+0

@ user186246これは意味があります。しかし、私は混乱がないことを確かめるために、あなたのパラメータの名前をどのような方法にしてもかまいません。 –

+0

なぜそれがアンフックに失敗しているのか分かりますか? – user186246

3

変更:

this.backgroundWorker1.RunWorkerCompleted -= new RunWorkerCompletedEventHandler(backgroundWorker1_RunWorkerCompleted); 

へ:

this.backgroundWorker1.RunWorkerCompleted -= backgroundWorker1_RunWorkerCompleted; 

コード内の誤りです。 (同様に、その隣にある2つ)

しかし、率直に言って、何が起こっているのか分かりません。 RunWorkerAsync();コマンドでBackgroundWorkerに電話しないと、接続されていても実行されません。だから何度も起こっていることはあなたが見ていることですか? のいずれかがBackgroundWorkerのときに2回呼び出されるのはRunWorkerCompletedですか?

BackgroundWorkerをそのまま使用したい場合は、にはが必要です。何も登録を解除する必要はありません。 RunWorkerAsync();に再度電話するまでは何も起こりません。にはのイベントが登録されます。

+0

+1 - フック/アンフックプロセスを必要としない点が優れています。 –

+0

私はそれを変えましたが、まだイベントを引き離していないと言いました – user186246

関連する問題