可以C#WinForm静态void主要不捕获异常吗?

Ian*_*Ian 7 c# exception winforms

我有一个WinForm应用程序编写的C#地方,我把一个try-catch块放在Program.cs程序入口中的static void Main方法,就像这样在应用程序的开头:

using System;
using System.IO;
using System.Windows.Forms;

namespace T5ShortestTime {
    static class Program {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main() {
            try {
                Application.EnableVisualStyles();
                Application.SetCompatibleTextRenderingDefault(false);
                Application.Run(new T5ShortestTimeForm());
            } catch (Exception e) {
                string errordir = Path.Combine(Application.StartupPath, "errorlog");
                string errorlog = Path.Combine(errordir, DateTime.Now.ToString("yyyyMMdd_HHmmss_fff") + ".txt");
                if (!Directory.Exists(errordir))
                    Directory.CreateDirectory(errordir);                
                File.WriteAllText(errorlog, e.ToString());              
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,它Application被放在一个try-catch块中,在catch块中,它唯一能做的就是创建一个错误日志文件.

现在,到目前为止一切顺利.我的应用程序运行良好,如果遇到崩溃,最后Exception应该被try-catch块捕获并存储在错误日志文件中.

但是,当我运行我的程序一段时间后,我得到一个未处理的异常(null引用).让我感到惊讶的是,异常不会创建错误日志文件.

现在,这篇文章显示它可能是由(ThreadExceptionHandleProcessCorruptedStateExceptions两个最受欢迎的答案)引起的,但我的案例显示了一个简单的null引用异常:

Problem signature:
  Problem Event Name:   CLR20r3
  Problem Signature 01: T5ShortestTime.exe
  Problem Signature 02: 2.8.3.1
  Problem Signature 03: 5743e646
  Problem Signature 04: T5ShortestTime
  Problem Signature 05: 2.8.3.1
  Problem Signature 06: 5743e646
  Problem Signature 07: 182
  Problem Signature 08: 1b
  Problem Signature 09: System.NullReferenceException
  OS Version:   6.3.9600.2.0.0.272.7
  Locale ID:    1033
  Additional Information 1: bb91
  Additional Information 2: bb91a371df830534902ec94577ebb4a3
  Additional Information 3: aba1
  Additional Information 4: aba1ed7202d796d19b974eec93d89ec2

Read our privacy statement online:
  http://go.microsoft.com/fwlink/?linkid=280262

If the online privacy statement is not available, please read our privacy statement offline:
  C:\Windows\system32\en-US\erofflps.txt
Run Code Online (Sandbox Code Playgroud)

那为什么会这样?

Han*_*ant 5

try-catch块应捕获最后一个Exception

这不会发生.除了一种情况,当您运行附带调试器的程序时.所以你肯定会相信它会起作用,每个人总是开始用F5运行他们的程序一段时间.

Application.Run()在其代码中有一个反向停止引发事件,try/catch-em-all在事件处理程序抛出未处理的异常时引发Application.ThreadException事件.这回站是真的,真的有必要,特别是在Windows x64版本7 非常不好的事情发生时,有没有异常处理程序.但是,当您使用调试器运行时,该后退不会到位,这使得未处理的异常难以调试.

因此,当您调试时,您的catch子句将运行.使未处理的异常太难以调试.当您在没有调试器的情况下运行时,您的catch子句将无法运行,您的程序将崩溃,就像您所描述的那样.使未处理的异常太难调试.

所以不要这样做.Application.Run()如何处理未处理的异常是使用Application.SetUnhandledExceptionMode()方法配置的.你会更喜欢这个版本:

    [STAThread]
    static void Main() {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        if (!System.Diagnostics.Debugger.IsAttached) {
            Application.SetUnhandledExceptionMode(UnhandledExceptionMode.ThrowException);
            AppDomain.CurrentDomain.UnhandledException += LogException;
        }
        Application.Run(new Form1());
    }

    private static void LogException(object sender, UnhandledExceptionEventArgs e) {
        string errordir = Path.Combine(Application.StartupPath, "errorlog");
        string errorlog = Path.Combine(errordir, DateTime.Now.ToString("yyyyMMdd_HHmmss_fff") + ".txt");
        if (!Directory.Exists(errordir))
            Directory.CreateDirectory(errordir);
        File.WriteAllText(errorlog, e.ToString());
        AppDomain.CurrentDomain.UnhandledException -= LogException;
        MessageBox.Show("Error details recorded in " + errorlog, "Unexpected error");
        Environment.Exit(1);
    }
Run Code Online (Sandbox Code Playgroud)

使用此代码,您可以毫无问题地调试未处理的异常.Debugger.IsAttached测试确保调试器在事件处理程序崩溃时始终停止.如果没有调试器,它会禁用Application.ThreadException事件(它非常无用)并且倾向于监听所有异常.包括在工作线程中引发的那些.

您应该向用户发出警报,以便窗口不会消失而没有任何痕迹.我打算推荐MessageBox但是注意到这个bug目前在Windows 10上又回来了.叹了口气.


归档时间:

查看次数:

673 次

最近记录:

9 年,9 月 前