0

私のwinformsプロジェクトでは、BackgroundWorkerを実行するフォームを取得しました。基本的にはシミュレーションなので、ある時点で解決できますが、ユーザーが停止することもできるため、いずれかの方法で終了すると、結果を再描画する必要があります。メイン ウィンドウを閉じるとその参照が null になるという事実に問題がありましたが、BW は引き続き ReportProgress を起動でき、例外が発生します。

私の BackgroundWorker (簡略化されたコード):

void backgroundWorkerRunSimulation_DoWork(object sender, DoWorkEventArgs e)
{
    bool ShouldContinue = true;
    do
    {
        SomeHeavyComputing();
        if(CheckIfSimulationDone() | backgroundWorkerRunSimulation.CancellationPending)
            ShouldContinue=false;

        //Redrawing results on the interface
        if (AlwaysRefresh | !ShouldContinue)
            UpdateGUI();    //<--Method invoked on form's thread

        //Reporting progress
        backgroundWorkerRunSimulation.ReportProgress(0, SomeReportingObject);
    }
    while(ShouldContinue);
}

ReportProgress:

    private void backgroundWorkerRunSimulation_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        UpdateStatusBar((GUIReportInfo)e.UserState);//<-also invoked on form's thread

    }

どこ

void UpdateStatusBar(GUIReportInfo ReportInfo)
{
    if (this.InvokeRequired)
    {
        ReportInfoDelegate updateStatusBar = new ReportInfoDelegate(UpdateStatusBar);
        this.Invoke(updateStatusBar, new object[] { ReportInfo });
    }
    else
        //Some assignments on form - crashes here, null reference exc
}

明らかに、UpdateStatusBar を起動するべきではありません。また、UpdateGUI (アナログ) がクラッシュしないことに驚いています。しかし、フォームがまだそこにあるかどうかを確認する方法はありますか? 追加:

this.Invoke(new MethodInvoker(delegate { this.Close(); }));

なぜそれが機能するのかわかりませんが、 FormClosing イベントに問題を解決するようです。とにかく、フォームのスレッドで Close() メソッドが起動されていませんか?

何かお役に立てば幸いです。

4

2 に答える 2

1

追加された呼び出しがイベントの順序を誤って変更しただけなので、クラッシュしないと思います。洗練された解決策は、FormClosing を実装してそこで BW を中止し、完了するまで待つことです。また、BW コードで「CancellationPending」を確認する必要があります。詳細はこちら:

http://msdn.microsoft.com/en-us/library/hybbz6ke.aspx

編集:ここからのトップ投票の回答は解決策を示しています: フォームのクロージングイベントでBackgroundWorkerを停止する方法は?

于 2013-08-04T15:45:45.970 に答える