Prism Async DelegateCommand 中的异常处理
Exception Handling in Prism Async DelegateCommand
我在异步 DelegateCommand (Prism 5) 中捕获异常时遇到了很多麻烦。
在 ViewModel 的构造函数中:
cmdModificarPedido = New DelegateCommand(Of Object)(AddressOf OnModificarPedido, AddressOf CanModificarPedido)
在视图模型中:
Private _cmdModificarPedido As DelegateCommand(Of Object)
Public Property cmdModificarPedido As DelegateCommand(Of Object)
Get
Return _cmdModificarPedido
End Get
Private Set(value As DelegateCommand(Of Object))
SetProperty(_cmdModificarPedido, value)
End Set
End Property
Private Function CanModificarPedido(arg As Object) As Boolean
Return True
End Function
Private Async Sub OnModificarPedido(arg As Object)
Try
Await Task.Run(Sub()
Throw New Exception("My Exception")
End Sub)
NotificationRequest.Raise(New Notification() With {
.Title = "OK",
.Content = "Command OK"
})
Catch ex As Exception
NotificationRequest.Raise(New Notification() With {
.Title = "Error",
.Content = ex.Message
})
End Try
End Sub
为什么异常没有被捕获?我知道这是另一个线程,但无论如何它都应该被外部 Try...Catch 块 (Try Catch outside of: await Task.Run(()) 捕获。
注意:这是 vb.net 代码,但 C# 解决方案也可以。
更新 2
一旦我知道我的调试器配置有问题(第一次机会异常),我写了一个更真实的例子来解决同样的问题:
Private Async Sub OnModificarPedido(arg As Object)
Try
Await Task.Run(Sub()
Try
throwMyException()
Catch ex As Exception
Throw New Exception(ex.Message)
End Try
End Sub)
NotificationRequest.Raise(New Notification() With {
.Title = "Pedido Modificado",
.Content = "Pedido " + pedido.numero.ToString + " modificado correctamente"
})
Catch ex As Exception
NotificationRequest.Raise(New Notification() With {
.Title = "Error",
.Content = ex.Message
})
End Try
End Sub
Public Async Sub throwMyException()
Throw New Exception("My Exception")
End Sub
现在当我按 F5 时它不会捕获异常。它在 "throwMyException()" 中中断,尽管它是在 Try Catch 块中调用的,但它不会捕获异常。
重要提示:如果我删除 "throwMyException" 中的 Async 词,它确实会捕获它!!!
我现在做错了什么?
谢谢
您发布的原始代码没有问题 - 调试器只是在您的代码出现之前捕捉到异常,这是完全正常的。
使用更新后的代码,问题是 Async Sub
的使用。无法从 Async Sub
方法中直接捕获异常。您应该改用 (non-Async
) Sub
或 Async Func(of Task)
。这个原则在我的 MSDN article on async best practices.
中被称为 "avoid async void"
我在异步 DelegateCommand (Prism 5) 中捕获异常时遇到了很多麻烦。
在 ViewModel 的构造函数中:
cmdModificarPedido = New DelegateCommand(Of Object)(AddressOf OnModificarPedido, AddressOf CanModificarPedido)
在视图模型中:
Private _cmdModificarPedido As DelegateCommand(Of Object)
Public Property cmdModificarPedido As DelegateCommand(Of Object)
Get
Return _cmdModificarPedido
End Get
Private Set(value As DelegateCommand(Of Object))
SetProperty(_cmdModificarPedido, value)
End Set
End Property
Private Function CanModificarPedido(arg As Object) As Boolean
Return True
End Function
Private Async Sub OnModificarPedido(arg As Object)
Try
Await Task.Run(Sub()
Throw New Exception("My Exception")
End Sub)
NotificationRequest.Raise(New Notification() With {
.Title = "OK",
.Content = "Command OK"
})
Catch ex As Exception
NotificationRequest.Raise(New Notification() With {
.Title = "Error",
.Content = ex.Message
})
End Try
End Sub
为什么异常没有被捕获?我知道这是另一个线程,但无论如何它都应该被外部 Try...Catch 块 (Try Catch outside of: await Task.Run(()) 捕获。
注意:这是 vb.net 代码,但 C# 解决方案也可以。
更新 2 一旦我知道我的调试器配置有问题(第一次机会异常),我写了一个更真实的例子来解决同样的问题:
Private Async Sub OnModificarPedido(arg As Object)
Try
Await Task.Run(Sub()
Try
throwMyException()
Catch ex As Exception
Throw New Exception(ex.Message)
End Try
End Sub)
NotificationRequest.Raise(New Notification() With {
.Title = "Pedido Modificado",
.Content = "Pedido " + pedido.numero.ToString + " modificado correctamente"
})
Catch ex As Exception
NotificationRequest.Raise(New Notification() With {
.Title = "Error",
.Content = ex.Message
})
End Try
End Sub
Public Async Sub throwMyException()
Throw New Exception("My Exception")
End Sub
现在当我按 F5 时它不会捕获异常。它在 "throwMyException()" 中中断,尽管它是在 Try Catch 块中调用的,但它不会捕获异常。
重要提示:如果我删除 "throwMyException" 中的 Async 词,它确实会捕获它!!!
我现在做错了什么?
谢谢
您发布的原始代码没有问题 - 调试器只是在您的代码出现之前捕捉到异常,这是完全正常的。
使用更新后的代码,问题是 Async Sub
的使用。无法从 Async Sub
方法中直接捕获异常。您应该改用 (non-Async
) Sub
或 Async Func(of Task)
。这个原则在我的 MSDN article on async best practices.