模拟环境中的异常.退出

本文关键字:异常 退出 环境 模拟 | 更新日期: 2023-09-27 17:50:47

生产控制台应用程序,每晚午夜前通过 Environment.Exit(0( 关闭,在 期间偶尔会遇到异常。Exit(( 使控制台应用程序挂起,并显示"应用程序已停止工作"屏幕。

这会导致进程无法正确清理,并且午夜后重新启动失败,因为先前的进程仍然徘徊。

由于我无法确定导致 Environment.Exit 中异常的原因,因此我希望至少在它发生时优雅地处理它,并确保该过程完全关闭。为此,我想模拟 .Exit(( 但我还没有找到会在 .退出((。

有谁知道如何模拟 Environment.Exit 期间的异常?

模拟环境中的异常.退出

当然,复制很容易:

private static void Main()
{
    try
    {
        new ItsATrap();
        Environment.Exit(0);
    }
    catch (Exception ex)
    {
        Console.WriteLine("During exit: {0}", ex);
    }
}
private class ItsATrap
{
    ~ItsATrap()
    {
        throw new InvalidOperationException("Ooops!");
    }
}

请注意,在上面的示例中,During exit文本永远不会打印。

您可以通过安装如下处理程序来捕获未经处理的异常:

AppDomain.CurrentDomain.UnhandledException += (sender, args)
    => Console.WriteLine("Unhandled: {0}", args.ExceptionObject);

这样,您就有机会记录它们。

所以......检查你的终结器,看看他们是否可以投掷。

此外,请确保它们不使用其他托管资源,因为最终确定顺序不是确定性的。像往常一样,Eric Lippert有一些关于这个主题的好文章可以阅读。

你这里有一个XY问题。您想要模拟异常,因为您不知道还可以执行哪些操作。与其模拟您不完全知道的东西,不如尝试找出问题的真正原因并修复它。

收集故障转储 (MSDN( 并将其加载到 Visual Studio 中。只要它位于 C# 代码中的某个位置,它就应该显示行号。

另请参阅:如何为 .NET 进行良好的故障转储?在 Stack Overflow 上。

按照其他答案中的建议修改代码可能会更改时间,并且可能会降低异常的可能性或发生在不同的位置。很高兴您可以重现问题并修复它,而不是稀释它。

使用已释放/最终的对象可能会导致它。发生这种情况是因为没有固定的定稿顺序,因此例如,尝试在已定稿的Stream上编写内容的手工记录器将导致异常(手工制作,因为"专业"记录器知道这一点:-((。

您可以尝试在调用记录在此期间发生的每个异常的Environment.Exit之前安装首次机会异常处理程序。像这样:

object lck = new object();
AppDomain.CurrentDomain.FirstChanceException += (sender, e) =>
{
    lock (lck)
    {
        File.AppendAllText("log.txt", string.Format("{0}: {1}", DateTime.Now, e.Exception.ToString()));
    }
};
Environment.Exit(0);