具体的には、MVVM で WPF を使用しています。これは、すべてのアクションが発生する WPF ウィンドウです。プロパティ、コマンドなどに対応するビュー モデル クラスを使用します。
次のように、Application.xaml.vb StartUp でメイン UI スレッドと非 UI スレッドの例外ハンドラーを設定しました。
Private Sub Application_DispatcherUnhandledException(sender As Object, e As Windows.Threading.DispatcherUnhandledExceptionEventArgs) Handles Me.DispatcherUnhandledException
' catches main UI thread exceptions only
ShowDebugOutput(e.Exception)
e.Handled = True
End Sub
Private Sub Application_Startup(sender As Object, e As StartupEventArgs) Handles Me.Startup
' catches background exceptions
Dim currentDomain As AppDomain = AppDomain.CurrentDomain
AddHandler currentDomain.UnhandledException, AddressOf UnhandledExceptionHandler
AddHandler System.Threading.Tasks.TaskScheduler.UnobservedTaskException, AddressOf BackgroundTaskExceptionHandler
End Sub
Sub UnhandledExceptionHandler(sender As Object, args As UnhandledExceptionEventArgs)
Dim ex As Exception = DirectCast(args.ExceptionObject, Exception)
ShowDebugOutput(ex)
End Sub
Sub BackgroundTaskExceptionHandler(sender As Object, args As System.Threading.Tasks.UnobservedTaskExceptionEventArgs)
Dim ex As Exception = DirectCast(args.Exception, Exception)
ShowDebugOutput(ex)
End Sub
この部分は動作します
これをテストしようとすると、意図的に例外をスローして動作します。[すべて選択] ボタンのクリックを処理するのは、実際には Sub の View Model にあります。
ボタン:
<Button Content="Select All" Height="23" Width="110" Command="{Binding SelectAllCommand}" />
正常にキャッチされた例外をスローしているコマンド:
Private Sub SelectAll()
Throw (New Exception("UI Thread exception"))
SetAllApplyFlags(True)
End Sub
この部分は機能しません
同じ MainWindow に、同様にコマンドにバインドされた別のボタンがあります。ただし、タスクを使用してバックグラウンドで作業を実行し、そこでスローされた例外はキャッチオール ハンドラーによってキャッチされません。
Private Sub GeneratePreview()
' run in background
System.Threading.Tasks.Task.Factory.StartNew(
Sub()
' ... stuff snipped out, issue is the same with or without the rest of the code here ...
Throw (New Exception("Throwing a background thread exception"))
End Sub)
End Sub
同様の質問がいくつかありますが、それらから実際に答えを見つけることができませんでした。ほとんどの場合、 AppDomain UnhandledException が答えのようですが、それは私のものではありません。この方法で非 UI スレッドでスローされる可能性のある例外をキャッチできるようにするには、正確に何を追加する必要がありますか?
私がやったこと
Application.xaml.vb でイベント ハンドラーを処理しているときに、TaskScheduler.UnobservedTaskException イベントを取得してイベント ハンドラーを呼び出すことができませんでした。しかし、私は他の答えからヒントを得ました。最終的には役に立ったので、答えとしてマークします。
ただし、これはアプリケーション レベルではないため、これがより大きなアプリケーションである場合は、タスクを使用したすべてのインスタンスでこれを複製する必要があります。これは私が探していたものではありませんでしたが、今はこれ以上時間を費やすつもりはありません。
Task内にtry-catchを配置することになりました。キャッチでは、Dispatcher.Invoke を使用して、ユーザー フレンドリーなダイアログと例外情報を引き続き表示することができました。
Private Sub GeneratePreview()
' run in background
System.Threading.Tasks.Task.Factory.StartNew(
Sub()
Try
' ... stuff snipped out, issue is the same with or without the rest of the code here ...
Throw (New Exception("Throwing a background thread exception"))
Catch ex As Exception
Application.Current.Dispatcher.Invoke(DispatcherPriority.Normal, DirectCast(
Sub()
HRNetToADImport.Application.ShowDebugOutput(ex)
End Sub, Action))
End Try
End Sub)
End Sub