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

问题描述 投票:0回答:1

有关于陷阱异常的MS文档https://learn.microsoft.com/en-us/dotnet/api/system.windows.forms.application.threadexception?view=windowsdesktop-7.0

但是这个文档是理论性的,并不绑定到 Windows Forms 和 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 类中不可用。

winforms exception .net-4.8 unhandled-exception
1个回答
0
投票

根据@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 建议中添加 3 条小评论:
(1) 当然重写是不可能的,只能重写。
(3) Msgbox(也许所有 Windows 窗体)在此工作流程中不起作用,我在文件上有简单的写入异常,在这种情况下它正在工作。
(3) 我在多线程应用程序中经常使用的替代方法(但不幸的是,在我当前的程序中不可能使用替代方法) - 将 Windows 窗体应用程序作为控制台应用程序启动,并且在绑定到所有 Windows 窗体事件后,比控制台应用程序进一步打开 Windows 窗体将完成。在这种情况下,控制台会在短时间内出现黑色屏幕,并且仅出现 Windows 窗体。

但是在 MyApplication 上重载 onStartup 是可行且更简单的方法,谢谢吉米。

© www.soinside.com 2019 - 2024. All rights reserved.