【发布时间】:2016-01-10 09:49:44
【问题描述】:
具体来说,我将 WPF 与 MVVM 一起使用。我有一个 MainWindow,它是一个 WPF 窗口,所有操作都在其中发生。它为其属性、命令等使用相应的 View Model 类。
我在 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
这部分有效
当我尝试通过故意抛出异常来测试它时,它可以工作。它实际上是在处理 Select All 按钮单击的 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 中还有另一个按钮类似地绑定到一个命令。但是,它使用一个任务在后台执行其工作,并且在那里抛出的异常不会被我的 catch-all 处理程序捕获。
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 事件时,我无法调用我的事件处理程序。但我从另一个答案中得到了提示,我将其标记为答案,因为它最终有所帮助。
但是,它不在应用程序级别,所以如果这是一个更大的应用程序,我必须在我使用任务的每个实例中复制它。这不是我真正想要的,但现在不愿意花更多时间。
我最终在任务中放置了一个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
【问题讨论】:
-
如果是4.5,需要msdn.microsoft.com/en-us/library/…
-
可能重复。 stackoverflow.com/questions/1472498/… ... 我认为@Drew Noakes 的答案是最好的答案。
-
啊哈。我看到了这个问题,但没有在 TaskScheduler.UnobservedTaskException 部分触发。那么我可以在 Application.xaml.vb 中添加这个处理程序 - 整个应用程序的一个处理程序吗?
-
@cscmh99 你能详细说明我如何使用它吗?我尝试在 StartUp 的 Application.xaml.vb 中添加一个处理程序:AddHandler System.Threading.Tasks.TaskScheduler.UnobservedTaskException,AddressOf BackgroundTaskExceptionHandler,但它仍然没有被调用。当我抛出那个后台异常时。
-
你能再等一会儿看看事件是否触发吗?该事件可能不会立即触发(可能会延迟几秒钟)。对不起,我不是一个真正的VB人。但我在 C# 中测试它就像你所做的一样,它确实有效。还要在 App 构造函数中注册事件。
标签: wpf vb.net mvvm exception-handling unobserved-exception