2009-06-26 21 views
-1

私はキャンセルできるバックグラウンドワーカーを雇っています。バックグラウンド労働者:キャンセル中の例外

通常のフローは、CancelPending変数がtrueになったときに割り込みを発生します(worker.CancelAsynch()を呼び出すUIでのユーザーのやりとりに応答します)。例外がスローされるのは(通常のフローが中断され、 、私は労働者がキャンセルされなかったときにそれらを報告すること(労働者 がキャンセルされたときに発生した例外から(黙ってそれらを無視するために)投げされている例外を区別できるようにしたい時に作業員が戻るので)

を投げています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()をやっているとき、e.CancelledはCompletedコールバックでfalseに設定されています(期待通りではありません)。私が を再度テストすると、「Trow exc」を作業者にコメントアウトすると、e.Cancelledは正しくtrueに設定されます。

私が望む情報を得る最もクリーンな方法は何ですか?完成したハンドラで例外がポップされたかどうかを、workerがcancellationPending状態になったときにスローしたかどうかを知りたいと思います。

(私の下手な英語のため申し訳ありませんが)

+0

作業コードはどのように見えますか? – Thies

+0

ワーカーは上のシミュレーションコードと似ています。関数呼び出しのいくつかのレベルを経て、CancellationPending(デリゲートを介してチェックされている)がtrueになったときに終了するループをそれぞれ実行します。 これらのループおよび機能は、フローが中断され、結果が破棄されるという事実を考慮して、「正常」な例外につながります。 なぜこれを尋ねますか? – jfburdet

答えて

0

あなた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; 
    } 
} 

あなたは保留中の取り消しを検出したときに、コードがOnDoWork(から返すことですBackgroundWorkerの契約を()従います方法を、例外をスローするのではなく)、キャンセルされたプロパティは現在のとおりになるはずです

+0

それほど素晴らしい代替手段は、OnDoWorkキャッチブロック(Me.WasCancelled = Me.CancellationPending)でtrueに設定できるBackgroundWorker派生クラスのパブリックメンバー "WasCancelled"を追加することです。このメンバは、完了したコールバックで使用できます。 – jfburdet

関連する問題