每天午夜前通过Environment.Exit(0)关闭的生产控制台应用程序,偶尔在.Exit()期间遇到异常,导致控制台应用程序挂起,“应用程序已停止工作”屏幕。 / p>
这导致流程无法正常清理,午夜后重新启动失败,因为先前的流程仍然存在。
由于我无法确定导致Environment.Exit中的异常的原因,因此我希望至少在它发生时正常处理它并确保进程完全关闭。为此,我想在.Exit()之后模拟崩溃,但是我无法找到在.Exit()期间会产生异常的场景。
有没有人知道如何模拟Environment.Exit期间的异常?
答案 0 :(得分:3)
当然,它很容易复制:
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来阅读这个主题。
答案 1 :(得分:1)
这里有XY问题。您想模拟异常,因为您不知道还能做什么。您应该尝试找出问题的真正原因并进行修复,而不是模拟您不确切知道的内容。
Collect a crash dump (MSDN)并将其加载到Visual Studio中。只要它在您的C#代码中的某个位置,就应该显示行号。
另请参阅:Stack Overflow上的How do I take a good crash dump for .NET?。
根据其他答案中的建议修改您的代码可能会改变时间,并且可能会使异常更不可能或发生在不同的位置。很高兴您可以重现问题并修复它而不是稀释它。
答案 2 :(得分:0)
使用已处置/已完成的物体可能会导致它。发生这种情况是因为没有固定的最终确定顺序,因此例如手写的记录器试图在已经完成的Stream
上写一些东西会导致异常(手工制作,因为"专业&#34记录员知道这个:-))。
您可以尝试在调用记录此期间发生的每个异常的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);