2

フォームがあります。フォームには、何かを行うロジック クラスがあります。この何かが行われている間、フォームをレスポンシブにしたいので、BackgroundWorker オブジェクトを作成します。また、ロジック クラスからフォームへの更新も取得したいと考えています。BackgroundWorker の進捗更新イベントを利用しようと考えました。

そこで、フォームのメソッドを worker.ProgressChanged にサブスクライブします。

public class MyForm : Form
{
    private LogicClass logicObject;

    public void StartOperation()
    {
        BGWorkerBase worker = new BGWorkerBase(logicObject);
        worker.DoWork += new DoWorkEventHandler(DoOperation);
        worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(OperationComplete);
        worker.ProgressChanged += new ProgressChangedEventHandler(worker_ProgressChanged);
        worker.RunWorkerAsync();
    }

    public void DoOperation()
    {
        logicObject.DoSomething();
    }

    private void worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        // Update form
    }
}

ロジック クラスの update イベントをサブスクライブし、ProgressChanged イベントを呼び出すカスタムの Backgroundworker を作成しました。

public class BGWorkerBase : BackgroundWorker
{
    public BGWorkerBase(LogicClass logicObject)
    {
        // connection is the logic class. it has an update event
        logicObject.UpdatePublished += new EventHandler(connection_UpdatePublished);
        this.WorkerReportsProgress = true;
    }
    // Here I invoke the backgroundworker OnProgressChangedEvent
    private void connection_UpdatePublished(object sender, EventArgs e)
    {
        OnProgressChanged(new ProgressChangedEventArgs(0, e));
    }
}

問題は、操作を繰り返しトリガーすると、更新が複数回公開されることです。確認したところ、接続オブジェクトにはパブリッシュ イベントにサブスクライブされた複数のワーカーが含まれていることがわかりました。したがって、ここで 2 つの問題を作成したようです
。 1. 1 つのイベントが複数回発行されます。2.接続オブジェクトに、バックグラウンド ワーカーへの参照を保持しています。バックグラウンド ワーカーは、ジョブが終了したら破棄する必要があります。

これを修正する最良の方法は何ですか?ワーカーがジョブを完了したらサブスクリプションを削除できるかもしれませんが、それは汚いようです。この状況を管理するためのより良い方法はありますか?

4

1 に答える 1

4

ワーカーが終了したら、イベントの登録を解除する必要があります。つまり、コードのどこかに次を追加する必要があります。

logicObject.UpdatePublished -= connection_UpdatePublished;

これにより、イベントを処理するために登録されたデリゲートのリストからイベント ハンドラーが削除されますUpdatePublished

この SO の質問/回答では、イベントを使用して誤ってメモリ リークを作成する方法について説明しています: イベント ハンドラのメモリ リークを回避する理由と方法は?

于 2013-01-14T13:48:21.820 に答える