winforms 如何在Windows窗体、Net Framework中捕获UIThreadException和UnhandledException

xytpbqjk  于 2023-10-23  发布在  Windows
关注(0)|答案(1)|浏览(117)

有关于陷阱异常https://learn.microsoft.com/en-us/dotnet/api/system.windows.forms.application.threadexception?view=windowsdesktop-7.0的MS文档
但是这个文档是理论上的,不绑定到Windows窗体和Visual Studio 2022,在Visual Studio中,我们有特殊的按钮来处理异常

这个类只允许捕获一个异常UnhandledException。我需要捕获第二个异常,因为我有复杂的多线程应用程序。
我创建了这个简单的测试来捕获ThreadException

Public Shared Sub ThreadExceptionEventHandler(ByVal sender As Object, ByVal e As ThreadExceptionEventArgs)
        MsgBox(e.Exception, MsgBoxStyle.OkOnly, "ThreadExceptionEventHandler")
End Sub

Private Async Sub MainForm_Load(sender As Object, e As EventArgs) Handles Me.Load
    AddHandler Application.ThreadException, AddressOf ThreadExceptionEventHandler '

    Await Task.Run(Sub()
                       Throw New Exception("test exception")
                   End Sub)
    ....

并在类MyApplication中尝试捕获Unhadled异常

Partial Friend Class MyApplication
    Private Sub MyApplication_UnhandledException(sender As Object, e As UnhandledExceptionEventArgs) Handles Me.UnhandledException
            MsgBox(e.Exception, MsgBoxStyle.OkOnly, "UnhandledException")
    End Sub
...

所以,看起来任何异常都必须被我的代码捕获,不是吗?用Visual Studio启动代码会显示未处理的错误

在控制台上启动程序不显示任何东西,程序关闭没有任何错误信息,这意味着陷阱任何异常不工作。为什么?为什么?
注意ThreadException在MyApplication类中不可用。

wwodge7n

wwodge7n1#

根据@Jimi的建议,最终的解决方案就在那里

Partial Friend Class MyApplication

    Public Shared Sub ThreadExceptionEventHandler(ByVal sender As Object, ByVal e As ThreadExceptionEventArgs)
        Dim Data() As Byte = System.Text.UTF8Encoding.UTF8.GetBytes(e.Exception.Message)
        My.Computer.FileSystem.WriteAllBytes(IO.Path.Combine(IO.Path.GetDirectoryName(Assembly.GetEntryAssembly().Location), Now.ToBinary.ToString & ".txt"), Data, True)
    End Sub

    Private Overloads Sub OnStartup()
        AddHandler System.Windows.Forms.Application.ThreadException, AddressOf ThreadExceptionEventHandler
    End Sub

    Private Sub MyApplication_Startup(sender As Object, e As StartupEventArgs) Handles Me.Startup
        My.Application.DoEvents()
    End Sub

    Private Sub MyApplication_UnhandledException(sender As Object, e As UnhandledExceptionEventArgs) Handles Me.UnhandledException
        Dim Data() As Byte = System.Text.UTF8Encoding.UTF8.GetBytes(e.Exception.Message)
        My.Computer.FileSystem.WriteAllBytes(IO.Path.Combine(IO.Path.GetDirectoryName(Assembly.GetEntryAssembly().Location), Now.ToBinary.ToString & ".txt"), Data, True)
    End Sub

给Jimi的建议添加两个小评论:
(1)Msgbox(也许所有的windows窗体)不工作在这个工作流中,我有一个简单的写异常文件,在这种情况下,它的工作。
(2)另一种方法我经常在多线程应用程序中使用(但不幸的是,另一种方法在我目前的程序中是不可能的)-是将Windows窗体应用程序作为控制台应用程序启动,然后比控制台应用程序进一步打开Windows窗体,绑定到所有Windows窗体事件后将完成。在这种情况下,黑色的控制台屏幕出现在短时间内,只比Windows窗体出现。
但是在MyApplication上重载或覆盖onStartup是可行的,也是更简单的方法,谢谢Jimi。当然,如果我们只想捕获线程异常,捕获常见的未处理异常需要注解。
根据@Jimi评论,重写也是可行的解决方案

Protected Overrides Function OnStartup(e As StartupEventArgs) As Boolean
        AddHandler System.Windows.Forms.Application.ThreadException, AddressOf ThreadExceptionEventHandler
        Return MyBase.OnStartup(e)
    End Function

相关问题