【问题标题】:Simulate Exception in Environment.Exit在 Environment.Exit 中模拟异常
【发布时间】:2015-05-26 20:16:41
【问题描述】:

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

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

由于我无法确定导致 Environment.Exit 中异常的原因,我想至少在它发生时优雅地处理它并确保进程完全关闭。为此,我想在 .Exit() 之后模拟崩溃,但我无法找到会在 .Exit() 期间产生异常的场景。

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

【问题讨论】:

标签: c# exception


【解决方案1】:

当然,复制很容易:

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 有一些关于这个主题的 good articles 可供阅读。

【讨论】:

  • 谢谢,正是我要找的东西
【解决方案2】:

这里有一个 XY 问题。你想模拟一个异常,因为你不知道你还能做什么。与其模拟您并不完全了解的事物,不如尝试找出问题的真正原因并加以解决。

Collect a crash dump (MSDN) 并将其加载到 Visual Studio 中。只要它在您的 C# 代码中的某个位置,它就会向您显示行号。

另请参阅:How do I take a good crash dump for .NET? 在 Stack Overflow 上。

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

【讨论】:

  • 您认为这是可以修复的。我将此追踪到我无法控制的第 3 部分组件。此外,这是作为分布式多进程系统的一部分发生的,该问题每 1-2 个月按我无法复制的事件顺序发生一次。由于我的预期结果是关闭进程,我认为更好的选择是确定如何关闭进程,尽管在此过程中抛出异常
  • @TJF:作为问题的一部分,这将是很好的信息。
【解决方案3】:

使用已处理/已完成的对象可能会导致它。发生这种情况是因为没有固定的完成顺序,例如,一个手工制作的记录器试图在已完成的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);

【讨论】:

  • 应用程序不会因为第一次机会异常而崩溃。为什么不为第二次机会异常安装未处理的异常处理程序?
  • @ThomasWeller 它被称为UnhandledException...当我必须调试某些东西时,我更喜欢看到FirstChanceException,因为他们通常有更多信息...可能会有例外这是由其他异常引起的(如果在 catch {} 块内使用记录器,如果记录器已经部分处理,则真正的异常可能会导致另一个异常,异常会隐藏真正发生的事情)。这是测试代码。您可以分别登录并快乐地生活。
  • @xanatos 如果您调用 Environment.Exit,则不会执行 catch
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-11-06
  • 2017-01-20
  • 2014-11-07
  • 1970-01-01
  • 1970-01-01
  • 2023-03-22
  • 1970-01-01
相关资源
最近更新 更多