73

私の WinForms アプリは、多数のBackgroundWorkerオブジェクトを使用して、データベースから情報を取得します。私が BackgroundWorker を使用しているのは、実行時間の長いデータベース クエリ中に UI がブロックされないようにし、スレッド モデルを簡素化できるためです。

これらのバックグラウンド スレッドの一部で時折 DatabaseExceptions が発生しています。また、デバッグ中にワーカー スレッドでこれらの例外の少なくとも 1 つを確認しました。私は、これらの例外がタイムアウトであるとかなり確信しています。

私の質問は、これらのバックグラウンド ワーカー スレッドのいずれかで未処理の例外が発生した場合に何が起こるかについてです。

別のスレッドで例外をキャッチできるとは思いませんが、WorkerCompleted メソッドが実行されることを期待できますか? 例外を調べることができる BackgroundWorker のプロパティまたはメソッドはありますか?

4

5 に答える 5

79

コードで処理できない例外が操作で発生した場合、 は例外をBackgroundWorkerキャッチしてRunWorkerCompletedイベント ハンドラに渡します。イベント ハンドラでは、 の Error プロパティとして公開されますSystem.ComponentModel.RunWorkerCompletedEventArgs。Visual Studio デバッガーで実行している場合、デバッガーは、未処理の例外が発生した DoWork イベント ハンドラーのポイントで中断します。

http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.dowork.aspx

于 2008-11-03T13:50:28.597 に答える
34

私はBackgroundWorker何年にもわたって完全に使用しており、それを深く知っています。

つい最近、 Myは単に I が に入っているときに をキャッチRunWorkerCompletedしません。ただし、未処理の例外が発生しました。キャッチインはベストプラクティスではないため、意味がありません。e.ErrorThrow New Exception("Test")DoWorkDoWorke.Error

Formnewで newを作成しようとするとBackgroundWorker、正常e.ErrorRunWorkerCompleted処理されました。私の複雑な中に何か問題があるはずBackgroundWorkerです。

グーグルとデバッグの数日後、エラーを試みます。私はこれを私の中で見つけましたRunWorkerCompleted

  • e.Error最初に、次にe.Cancelled、最後にチェックするe.Result
  • e.Resultifを取得しないでくださいe.Cancelled = True
  • e.Resultif e.Erroris not null(またはNothing) **を取得しない

** ここが懐かしい。e.Resultif e.Erroris not null(または)を使用しようとするとNothing、未処理の例外がスローされます。


更新:e.Result get プロパティ の .NET 設計では、最初にチェックするように設計されています。エラーが発生した場合は、 .NETe.Errorから同じ例外が再スローされDoWorkます。そのため、未処理の例外RunWorkerCompletedが発生しますが、実際には例外は から発生しDoWorkます。

で行うベスト プラクティスは次のRunWorkerCompletedとおりです。

If e.Error IsNot Nothing Then
  ' Handle the error here
Else
  If e.Cancelled Then
    ' Tell user the process canceled here
  Else
    ' Tell user the process completed
    ' and you can use e.Result only here.
  End If
End If

すべての DoWork、ProgressChanged、および RunWorkerCompleted にアクセスできるオブジェクトが必要な場合は、次のように使用します。

Dim ThreadInfos as Dictionary(Of BackgroundWorker, YourObjectOrStruct)

好きな場所に簡単にアクセスできThreadInfos(sender).Fieldます。

于 2010-04-14T09:46:16.223 に答える
11

デフォルトでは、BackgroundWorker によってキャッチされて保存されます。MSDN から:

コードで処理できない例外が操作で発生した場合、BackgroundWorker は例外をキャッチし、それを RunWorkerCompleted イベント ハンドラーに渡します。この例外は System.ComponentModel.RunWorkerCompletedEventArgs の Error プロパティとして公開されます。Visual Studio デバッガーで実行している場合、デバッガーは、未処理の例外が発生した DoWork イベント ハンドラーのポイントで中断します。

于 2008-11-03T13:54:24.423 に答える
4

すでに指摘したように:

コードで処理できない例外が操作で発生した場合、BackgroundWorker は例外をキャッチし、それを RunWorkerCompleted イベント ハンドラーに渡します。この例外は System.ComponentModel.RunWorkerCompletedEventArgs の Error プロパティとして公開されます。

これは、元のスレッドとやり取りするときはいつでも重要です。たとえば、例外の結果をフォームの何らかのラベルに書き込む場合は、BackgroundWorker の DoWork で例外をキャッチするのではなく、RunWorkerCompletedEventArgs から e.Error を処理する必要があります。

リフレクターを使用して BackgroundWorker コードを分析すると、すべてが非常に簡単に処理されていることがわかります。DoWork は try-catch ブロックで実行され、例外は RunWorkerCompleted に渡されます。これが、DoWork イベントですべての例外を常にキャッチする「優先」方法に同意しない理由です。

要するに、元の質問に答えるには:

はい- RunWorkerCompleted が常に起動されることを期待できます。

RunWorkerCompletedの e.Error を使用して、他のスレッドの例外を確認します。

于 2011-06-20T09:21:31.187 に答える
4

これは、デバッガーが接続されていない場合にのみ機能します。Visual Studio から実行すると、デバッガーは DoWork メソッドで未処理の例外をキャッチし、実行を中断しますが、[続行] をクリックすると RunWorkerCompleted に到達し、例外を読み取ることができます。 e.Error フィールド経由。

于 2011-08-26T13:18:00.360 に答える