捕获WPF中非UI线程的所有异常处理程序
具体来说,我将WPF与MVVM一起使用。我有一个主窗口,这是一个WPF窗口,所有的动作都发生在这里。它将相应的视图模型类用于其属性、命令等 我在Application.xaml.vb启动中设置了主UI线程和非UI线程异常处理程序,如下所示:捕获WPF中非UI线程的所有异常处理程序,wpf,vb.net,mvvm,exception-handling,unobserved-exception,Wpf,Vb.net,Mvvm,Exception Handling,Unobserved Exception,具体来说,我将WPF与MVVM一起使用。我有一个主窗口,这是一个WPF窗口,所有的动作都发生在这里。它将相应的视图模型类用于其属性、命令等 我在Application.xaml.vb启动中设置了主UI线程和非UI线程异常处理程序,如下所示: Private子应用程序\u DispatcherUnandledException(发件人作为对象,e作为Windows.Threading.DispatcherUnandledExceptionEventArgs)处理Me.DispatcherUnand
Private子应用程序\u DispatcherUnandledException(发件人作为对象,e作为Windows.Threading.DispatcherUnandledExceptionEventArgs)处理Me.DispatcherUnandledException
'仅捕获主UI线程异常
ShowDebugOutput(例如异常)
e、 已处理=真
端接头
私有子应用程序_Startup(发送方作为对象,e作为StartupEventArgs)处理我。Startup
'捕获背景异常
将currentDomain设置为AppDomain=AppDomain.currentDomain
AddHandler currentDomain.UnhandledException,UnhandledExceptionHandler的地址
AddHandler System.Threading.Tasks.TaskScheduler.UnobservedTaskException,BackgroundTaskExceptionHandler的地址
端接头
子UnhandledExceptionHandler(发送方作为对象,参数作为UnhandledExceptionEventArgs)
Dim ex As Exception=DirectCast(args.ExceptionObject,Exception)
ShowDebugOutput(ex)
端接头
Sub-BackgroundTaskExceptionHandler(发送方作为对象,参数作为System.Threading.Tasks.UnobservedTaskExceptionEventArgs)
Dim ex As Exception=DirectCast(args.Exception,Exception)
ShowDebugOutput(ex)
端接头
这部分有效
当我试图通过故意抛出异常来测试这一点时,它是有效的。实际上,它位于子对象中处理“全选”按钮单击的视图模型中
按钮:
<Button Content="Select All" Height="23" Width="110" Command="{Binding SelectAllCommand}" />
这部分不行
在同一主窗口中,还有另一个按钮类似地绑定到命令。但是,它使用一个任务在后台执行它的工作,在那里抛出的异常不会被我的“捕获所有”处理程序捕获
Private Sub-GeneratePreview()
“在后台运行
System.Threading.Tasks.Task.Factory.StartNew(
分()
“…被剪掉的东西,问题是相同的,无论是否有剩余的代码在这里。。。
抛出(新异常(“抛出后台线程异常”))
末端接头)
端接头
有几个类似的问题,但我还不能从中找出我的答案。AppDomain UnhandledException似乎是大多数情况下的答案,但对我来说不是。为了捕获可能以这种方式在非UI线程中抛出的异常,我必须添加什么
我最终做了什么
当我在Application.xaml.vb中处理TaskScheduler.UnobservedTaskException事件时,我无法让它调用我的事件处理程序。但我从另一个答案中得到了一些提示,我将把它标记为答案,因为它最终起到了帮助作用
但是,它不在应用程序级别,因此如果这是一个更大的应用程序,我必须在使用任务的每个实例中复制它。这不是我真正想要的,但我现在不愿意花更多的时间在上面
最后,我在任务中加入了一个try-catch。在catch中,我能够使用Dispatcher.Invoke仍然显示一个带有异常信息的用户友好对话框
Private Sub-GeneratePreview()
“在后台运行
System.Threading.Tasks.Task.Factory.StartNew(
分()
尝试
“…被剪掉的东西,问题是相同的,无论是否有剩余的代码在这里。。。
抛出(新异常(“抛出后台线程异常”))
特例
Application.Current.Dispatcher.Invoke(DispatcherPriority.Normal,DirectCast(
分()
HRNetToADImport.Application.ShowDebugOutput(ex)
结束(行动小组)
结束尝试
末端接头)
端接头
桑德拉
有一种方法可以从后台任务中捕获异常。我承认我的解决方案不是全球性的,但至少它抓住并防止了崩溃
Private Async Sub Button_Click(sender As Object, e As RoutedEventArgs)
Dim t As Task = 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)
Try
Await t
Catch ex1 As Exception
Debug.WriteLine("Exception from inside task " & ex1.Message)
End Try
End Sub
我想这可能会有帮助,可能是你,可能是其他人 TaskScheduler.UnobservedTaskException事件是您要从应用程序启动订阅的事件 当出现故障的任务的未观察到的异常即将触发异常升级策略时发生,默认情况下,该策略将终止该进程 此AppDomain范围的事件提供了一种机制来防止触发异常升级策略(默认情况下,该策略会终止进程) 注意:事件可能不会立即触发(可能会延迟几秒钟)。您可以想象,在到达UnobservedTaskeException事件之前,有一些调用堆栈冒泡和正常异常操作的上下文切换操作 我想指出的一点是,必须用通用异常处理程序包装整个应用程序,以防止应用程序终止。但是,请记住,对所有可能引发异常的路径实施适当的异常处理也是必须的。Sandra 我读了cscmh99提案, 把你的代码,并尝试运行,它的工作 我的意思是你可以订阅
任务调度程序。未观察到的任务异常
- 然后您将捕获
未观察到的异常
.Wait()
或.Result
等待的任务中的异常Private子按钮\u单击(发送者作为对象,e作为RoutedEventArgs)
下面是一个未被发现的例外
System.Threading.Tasks.Task.Factory.StartNew(
分()
抛出(新异常(“抛出后台线程异常”))
末端接头)
下面是一个观察到的例外
'ObservedException,因为调用了.Wait()(或.Result)
“你不能使用UnobservedExcepti