C# 处理未处理的异常问题
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/406385/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Handling unhandled exceptions problem
提问by agnieszka
I wanted to set some handler for all the unexpected exceptions that I might not have caught inside my code. In Program.Main()
I used the following code:
我想为我的代码中可能没有捕获的所有意外异常设置一些处理程序。在Program.Main()
我使用以下代码:
AppDomain.CurrentDomain.UnhandledException
+= new UnhandledExceptionEventHandler(ErrorHandler.HandleException);
But it didn't work as I expected. When I started the application in debugging mode and threw an exception it did call the handler, but afterwards the exception helper in Visual Studio popped up as if the exception occurred without any handling. I tried Application.Exit() inside the handler but it didn't work as well.
但它并没有像我预期的那样工作。当我在调试模式下启动应用程序并抛出异常时,它确实调用了处理程序,但之后 Visual Studio 中的异常助手弹出,好像异常发生时没有任何处理。我在处理程序中尝试了 Application.Exit() ,但效果不佳。
What I would like to achieve is that the exception is handled with my handler and then the application closes nicely. Is there any other way to do it or am I using the code above in the wrong way?
我想要实现的是用我的处理程序处理异常,然后应用程序很好地关闭。有没有其他方法可以做到,或者我是否以错误的方式使用了上面的代码?
采纳答案by Peter Lindholm
It's because you're running it through Visual Studio in Debug mode. If you release and install your app somewhere else, nothing but your global exception handler will be processed.
这是因为您在调试模式下通过 Visual Studio 运行它。如果您在其他地方发布并安装您的应用程序,则只会处理您的全局异常处理程序。
回答by Marc Gravell
Note that unhandled exceptions are still pretty fatal; you can only really use this for logging, or maybe some hasty close-down. Neither this nor Application.ThreadException
can be used as a global sink for errors.
请注意,未处理的异常仍然非常致命;您只能真正将其用于日志记录,或者可能是一些仓促的关闭。这也Application.ThreadException
不能用作错误的全局接收器。
The better approach is to add proper handling - for example, around your entire Main()
logic. Note that even thiscan't catch a few exceptions, such as errors during form-load (which get particularly nasty - you can catch them with a debugger attached, but not without).
更好的方法是添加适当的处理 - 例如,围绕整个Main()
逻辑。请注意,即使这样也无法捕获一些异常,例如表单加载期间的错误(这会变得特别令人讨厌 - 您可以通过附加调试器来捕获它们,但不能没有)。
回答by peSHIr
Normally I use something like this to try and catch all unexpected top-level exceptions.
通常我会使用这样的方法来尝试捕获所有意外的顶级异常。
using System;
static class Program
{
[STAThread]
static void Main(string[] argv)
{
try
{
AppDomain.CurrentDomain.UnhandledException += (sender,e)
=> FatalExceptionObject(e.ExceptionObject);
Application.ThreadException += (sender,e)
=> FatalExceptionHandler.Handle(e.Exception);
// whatever you need/want here
Application.Run(new MainWindow());
}
catch (Exception huh)
{
FatalExceptionHandler.Handle(huh);
}
}
static void FatalExceptionObject(object exceptionObject) {
var huh = exceptionObject as Exception;
if (huh == null) {
huh = new NotSupportedException(
"Unhandled exception doesn't derive from System.Exception: "
+ exceptionObject.ToString()
);
}
FatalExceptionHandler.Handle(huh);
}
}
Maybe it is something you find helpful too? This main code routes all three ways of catching unexpected top-level exceptions through one method call. All you now need is a static class FatalExceptionHandler
that includes your top-level exception handling in its Handle
method.
也许这对您也有帮助?此主要代码通过一个方法调用路由所有三种捕获意外顶级异常的方法。您现在需要的只是一个静态类FatalExceptionHandler
,它在其Handle
方法中包含您的顶级异常处理。
And really, any application developer knows there are really just two things to do there:
实际上,任何应用程序开发人员都知道在那里要做的只有两件事:
- Show/log the exception like you see fit
- Make sure you exit/kill the application process
- 显示/记录您认为合适的异常
- 确保退出/终止应用程序进程
If you think item two is strange, remember that we only bother to do this in the first place for really exceptional situations. These things are probably bugs that need changes to your application to be accurately addressed. Any other exception handling - the functional kind - should be lower down inside your actual program code, catching specific kinds of exceptions where this makes sense and handling them there in the way that makes sense. Anything else should bubble up to your FatalExceptionHandler
to make itself known and stop the possibly crippled program from working from corrupted state
如果您认为第 2 条很奇怪,请记住,我们首先只会在非常特殊的情况下才会这样做。这些事情可能是需要更改您的应用程序才能准确解决的错误。任何其他异常处理 - 函数类型 - 应该在您的实际程序代码中较低,捕获特定类型的异常,并以合理的方式处理它们。其他任何事情都应该冒泡到您FatalExceptionHandler
那里以让自己知道并阻止可能瘫痪的程序从损坏状态工作
Dead programs tell no lies... ;-)
死程序不会说谎...... ;-)
回答by Yariv
Perhaps what you're looking for is Environment.Exit(int errorcode)
也许你正在寻找的是 Environment.Exit(int errorcode)
回答by bohdan_trotsenko
That behavior is by design.
这种行为是设计使然。
But there isa work-around.
但是,是一个变通。
Either you call Process.GetCurrentProcess().Kill();
within the handler, or simply do not let the handler end.
要么Process.GetCurrentProcess().Kill();
在处理程序中调用,要么干脆不要让处理程序结束。
Check out the example:
查看示例:
class Program
{
void Run()
{
AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
Console.WriteLine("Press enter to exit.");
do
{
(new Thread(delegate()
{
throw new ArgumentException("ha-ha");
})).Start();
} while (Console.ReadLine().Trim().ToLowerInvariant() == "x");
Console.WriteLine("last good-bye");
}
int r = 0;
void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
Interlocked.Increment(ref r);
Console.WriteLine("handled. {0}", r);
Console.WriteLine("Terminating " + e.IsTerminating.ToString());
Thread.CurrentThread.IsBackground = true;
Thread.CurrentThread.Name = "Dead thread";
while (true)
Thread.Sleep(TimeSpan.FromHours(1));
//Process.GetCurrentProcess().Kill();
}
static void Main(string[] args)
{
Console.WriteLine("...");
(new Program()).Run();
}
}
This should not be a default sink for exceptions, surely.
当然,这不应该是异常的默认接收器。
But this should be done to report exceptions gracefully.
但是为了优雅地报告异常,应该这样做。