【问题标题】:What is the recommended way to handle TaskScheduler.UnobservedTaskException in GUI apps?在 GUI 应用程序中处理 TaskScheduler.UnobservedTaskException 的推荐方法是什么?
【发布时间】:2012-08-26 21:59:35
【问题描述】:

为了稳健性,我想为 TaskScheduler.UnobservedTaskException 添加一个处理程序。 处理程序会记录异常通知用户并关闭应用程序。

下面的实现有意义吗? 在 WPF 中是否可以在此处理程序中显示 MessageBox 或 Windows,或者这是一个坏主意,因为我们在未观察任务的终结器中运行?

Private Sub TaskSheduler_UnobservedTaskException(sender As Object, e As UnobservedTaskExceptionEventArgs)
Static _wasUserInformed As Boolean = False

e.SetObserved()

'Trace all Exceptions
e.Exception.Flatten.Handle(Function(ex As Exception)
                               'TODO trace and log Exception
                               Debug.Print("UnobservedTaskException: {0}", ex.Message)
                               Return True
                           End Function)

If Not _wasUserInformed Then
    'Show root Exception 
    _wasUserInformed = True
    Application.Current.Dispatcher.BeginInvoke(Sub()
                                                   'MessageBox.Show(e.Exception.GetBaseException.Message)

                                                   Dim win As New UnexpectedExceptionWindow
                                                   win.UnexpectedException = e.Exception.GetBaseException
                                                   win.ShowDialog()

                                                   Application.Current.Dispatcher.BeginInvoke(Sub() Application.Current.Shutdown())
                                               End Sub)
End If

结束子

[编辑] 作为我们讨论的结果,我想出了以下解决方案。

Private Sub TaskScheduler_UnobservedTaskException(sender As Object, e As UnobservedTaskExceptionEventArgs
                                                  ) Handles TaskScheduler.UnobservedTaskException
    Static _wasUserInformed As Boolean = False

    'Free the finalizer thread and execute on the UI thread to be able to inform user
    Dispatcher.BeginInvoke(Sub() LogException(e.Exception))
    e.SetObserved()
    If Not _wasUserInformed Then
        _wasUserInformed = True
        'Show first error 
        Dispatcher.BeginInvoke(Sub()
                                   NotifyUser(e.Exception)
                                   Application.Current.Shutdown()
                               End Sub)
    End If
End Sub

【问题讨论】:

    标签: .net vb.net exception-handling task-parallel-library


    【解决方案1】:

    这是一个很好的问题。由于此事件在终结器线程上运行(我已通过 Reflector 确认了这一点),因此我们不能长时间阻塞。这将停止处理终结器。

    所以答案是:这不是一个好的设计,因为 UI 操作的持续时间是无限的。

    更好的解决方案是将处理排队到一个新的Task,以便它在线程池上运行。

    这个答案取决于实现细节(终结器在单个线程上执行,事件在终结器线程上触发)。但至少对于支持 .NET 4.0 的应用来说,这个答案是有效的。

    【讨论】:

    • 但是,他也在调用 Dispatcher.BeginInvoke,所以唯一真正阻止终结器的是调试打印。如果他也将它包含在 BeginInvoke 操作中,那么阻止的方式就不会太多了。
    猜你喜欢
    • 2011-02-28
    • 1970-01-01
    • 2011-11-04
    • 2013-04-04
    • 1970-01-01
    • 2018-06-12
    • 2010-11-27
    • 2015-07-18
    • 1970-01-01
    相关资源
    最近更新 更多