-2

キャンセルできるバックグラウンド ワーカーがあります。

CancelPending 変数が true になると (worker.CancelAsynch() を呼び出す UI でのユーザー操作に応答して)、通常のフローはそれ自体を中断します。その場合、例外がスローされます (通常のフローが中断されるため、多くの null 参照例外がスローされます)

そのため、ワーカーが戻ったときに、ワーカーがキャンセルされたときにスローされた例外 (黙って無視するため) と、ワーカーがキャンセルされなかったときにスローされた例外 (UI に報告するため) を区別できるようにしたいと考えています。

私のコードは次のとおりです(c#/vbの混合で申し訳ありません...):

ワーカークラス:

Public Class ClassBaseGetObjectsWorker
    Inherits System.ComponentModel.BackgroundWorker
    

 Protected Overrides Sub OnDoWork(ByVal e As System.ComponentModel.DoWorkEventArgs)
        Try

            Dim cpt As Int16 = 0
            While cpt < 5
                System.Threading.Thread.Sleep(1000)
                cpt = cpt + 1
                If CheckForCancellation() Then
                    'Simulating exception due to cancel
                    Throw New Exception("Exception du to cancel !")
                End If
            End While

        Catch exc As Exception
            e.Cancel = Me.CancellationPending
            Throw exc
        End Try

    End Sub
End Class

コールバック:

void setObjSetCollWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) {
    if (e.Cancelled) {
        resultLabel.Text += "Canceled";
        //e.Error is selently ignored
    }
    else {
        if (e.Error != null) {
            //Reporting errors arising during normal (uncanceled) flow
            throw e.Error.InnerException;
        }
        else {
            //Worker process finished without error or being canceled.
            updateUIAfterBackgroundJob();
        }
    }
}

次に、worker.CancelAsynch() を実行しているときに、Completed コールバックで e.Cancelled が false に設定されます (これは私が期待したものではありません)。ワーカーで「Trow exc」をコメントアウトし、再度テストすると、e.Cancelled が正しく true に設定されます。

必要な情報を取得する最もクリーンな方法は何ですか?つまり、worker が cancelPending 状態にあったときに、完了したハンドラーでポップアウトする例外がスローされたかどうかを知りたいですか?

4

1 に答える 1

1

OnDoWork()実装でコードを構造化する最良の方法が、キャンセルを検出したときに例外をスローすることである場合は、次のようにします。

CancelExceptionを作成します:

public class CancelException: Exception {}

キャンセルが保留中であることを検出した場合は、このCancelExceptionをスローします。

if(CheckForCancellation()) throw new CancelException();

OnDoWork()メソッドのコードの周りにtry-catchを追加します。

protected override void OnDoWork(DoWorkEventArgs e){
  try{
    //...
  }
  catch(CancelException){
    // silently return
    return;
  }
}

そうすれば、コードはBackgroundWorker-contract(例外をスローするのではなく、保留中のキャンセルを検出したときにOnDoWork()から戻る)に従い、Canceledプロパティは期待どおりになるはずです。

于 2009-06-26T12:17:30.427 に答える