使用Application.ThreadException事件可以处理UI线程的异常,
并且可以阻止应用程序终止
使用 Application.UnhandledException 事件来处理非 UI 线程异常,
但是却并不能阻止应用程序终止
想请教下如何捕捉到UI 线程异常,阻止应用程序终止呢.?
我想要完成一个自动处理异常的模块,当有异常抛出后,检索异常来源,记录日志,并且处理异常后,重新执行出现异常的模块,
UnhandledException事件可以检索到异常的发生,但是处理后,应用程序还是会退出,
请教高手,还有没有别的更好的办法.?
处理AppDomain.CurrentDomain.UnhandledException事件,参考以下代码
更加复杂,或者灵活的解决方案,可以结合微软的Enterprise Library中的Exception Application Block,可以参考http://msdn.microsoft.com/en-us/library/ff648951.aspx
[STAThread] static void Main() { Application.ThreadException += new System.Threading.ThreadExceptionEventHandler(Application_ThreadException); AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException); Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new Form1()); } static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) { MessageBox.Show("抱歉,您的操作没有能够完成,请再试一次或者联系软件提供商"); LogUnhandledException(e.ExceptionObject); } static void Application_ThreadException(object sender, System.Threading.ThreadExceptionEventArgs e) { MessageBox.Show("抱歉,您的操作没有能够完成,请再试一次或者联系软件提供商"); LogUnhandledException(e.Exception); } static void LogUnhandledException(object exceptionobj) { //这里可以进一步地写日志 }
你好!!感谢回复!!
你的解决方案,我知道,当非UI线程抛出异常之后,会触发CurrentDomain_UnhandledException事件,
可是当执行完CurrentDomain_UnhandledException事件之后,应用程序就会退出,
现在我想在CurrentDomain_UnhandledException事件里处理异常,然后重新执行有异常的函数,或是模块,
@发粪图墙: 我这里运行的情况是不会退出。而是弹出我们自定义的那个对话框。你不要用调试状态
@陈希章:
当弹出对话框后,程序就会跳出这个窗口,
这时应用程序已经崩溃了,因此这个解决方案,还是有问题
@发粪图墙: 我一直这样用,不会出现你所提到的那个窗口呢。你单独建一个新项目,然后用这个代码再试一下。然后再排查一下看看你的程序是否还有什么特殊性
@陈希章: 我用一个窗体,里面三个按钮,
第一个是直接throw new Exception();
第二个是创建一个thread然后在thread中throw new Exception();
第三个是一个多线程组件,也是调用的throw new Exception();
第一个按钮ThreadException可以捕获到,
第二个UnhandledException可以捕获到,但是UnhandledException执行完后就会出现上面的窗口,然后应用程序崩溃
第三个是因为组件中有异常处理,因此不会捕获到,
我目前需要解决的就是第二种的情况,当异常捕获到的时候,不要崩溃
@发粪图墙: 我重现了你的问题,对于这种在异步的工作线程中抛出的异常,虽然可以捕捉到,但确实还是会出现你所提到的问题。
一个可行的解决方法是,不要自己去创建和管理Thread,而是应该使用BackgroundWorker组件,这就很容易地控制了。
BackgroundWorker worker = new BackgroundWorker(); worker.DoWork += (o, a) => { throw new Exception("test"); }; worker.RunWorkerCompleted += (o, a) => { if (a.Error != null) MessageBox.Show(a.Error.Message); }; worker.RunWorkerAsync();
@发粪图墙: 如果是使用4.0,则可以更加简单
Task.Factory.StartNew(() => { throw new Exception("test"); }).Start();
这个同样会创建一个新的线程,然后被捕获到。但不会退出了。
@陈希章: 子线程的异常虽然会被上层捕获到,但是线程内还是需要你自己捕获一次。
我用ThreadException就可以呀?试试直接执行exe程序,看看效果,不调试
ThreadException只能捕获ui线程的异常,非ui线程的异常捕获不到
在程序员出现ArgumentNullException 很容易让程序崩溃掉。、
CurrentDomain_UnhandledException 里面用
while (true)
{
if (glExitApp)
{
LogUnhandledException("--------" + strException + "--------");//异常后的处理,否则程序直接关闭
return;
}
System.Threading.Thread.Sleep(2 * 1000);
}