首页 新闻 会员 周边

C# winform程序全局异常处理

0
悬赏园豆:50 [已解决问题] 解决于 2013-04-15 10:18

使用Application.ThreadException事件可以处理UI线程的异常,
并且可以阻止应用程序终止

使用 Application.UnhandledException 事件来处理非 UI 线程异常,
但是却并不能阻止应用程序终止

想请教下如何捕捉到UI 线程异常,阻止应用程序终止呢.?

我想要完成一个自动处理异常的模块,当有异常抛出后,检索异常来源,记录日志,并且处理异常后,重新执行出现异常的模块,

UnhandledException事件可以检索到异常的发生,但是处理后,应用程序还是会退出,

请教高手,还有没有别的更好的办法.?

只会造轮子的主页 只会造轮子 | 老鸟四级 | 园豆:2274
提问于:2013-03-12 18:04
< >
分享
最佳答案
-1

处理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)
{
//这里可以进一步地写日志
}
收获园豆:50
陈希章 | 老鸟四级 |园豆:2538 | 2013-03-12 18:32

你好!!感谢回复!!

你的解决方案,我知道,当非UI线程抛出异常之后,会触发CurrentDomain_UnhandledException事件,

可是当执行完CurrentDomain_UnhandledException事件之后,应用程序就会退出,

现在我想在CurrentDomain_UnhandledException事件里处理异常,然后重新执行有异常的函数,或是模块,

只会造轮子 | 园豆:2274 (老鸟四级) | 2013-03-13 10:08

@发粪图墙: 我这里运行的情况是不会退出。而是弹出我们自定义的那个对话框。你不要用调试状态

陈希章 | 园豆:2538 (老鸟四级) | 2013-03-13 10:16

@陈希章: 

当弹出对话框后,程序就会跳出这个窗口,

这时应用程序已经崩溃了,因此这个解决方案,还是有问题

只会造轮子 | 园豆:2274 (老鸟四级) | 2013-03-14 15:42

@发粪图墙: 我一直这样用,不会出现你所提到的那个窗口呢。你单独建一个新项目,然后用这个代码再试一下。然后再排查一下看看你的程序是否还有什么特殊性

陈希章 | 园豆:2538 (老鸟四级) | 2013-03-14 18:18

@陈希章: 我用一个窗体,里面三个按钮,

第一个是直接throw new Exception();

第二个是创建一个thread然后在thread中throw new Exception();

第三个是一个多线程组件,也是调用的throw new Exception();

第一个按钮ThreadException可以捕获到,

第二个UnhandledException可以捕获到,但是UnhandledException执行完后就会出现上面的窗口,然后应用程序崩溃

第三个是因为组件中有异常处理,因此不会捕获到,

 

我目前需要解决的就是第二种的情况,当异常捕获到的时候,不要崩溃

只会造轮子 | 园豆:2274 (老鸟四级) | 2013-03-15 11:04

@发粪图墙: 我重现了你的问题,对于这种在异步的工作线程中抛出的异常,虽然可以捕捉到,但确实还是会出现你所提到的问题。

一个可行的解决方法是,不要自己去创建和管理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();

            
陈希章 | 园豆:2538 (老鸟四级) | 2013-03-15 11:29

@发粪图墙: 如果是使用4.0,则可以更加简单

Task.Factory.StartNew(() => { throw new Exception("test"); }).Start();

这个同样会创建一个新的线程,然后被捕获到。但不会退出了。

陈希章 | 园豆:2538 (老鸟四级) | 2013-03-15 11:37

@陈希章: 子线程的异常虽然会被上层捕获到,但是线程内还是需要你自己捕获一次。

ChuckLu | 园豆:514 (小虾三级) | 2015-08-05 14:21
其他回答(3)
0

我用ThreadException就可以呀?试试直接执行exe程序,看看效果,不调试

会长 | 园豆:12401 (专家六级) | 2013-03-14 18:12

ThreadException只能捕获ui线程的异常,非ui线程的异常捕获不到

支持(0) 反对(0) 只会造轮子 | 园豆:2274 (老鸟四级) | 2013-03-15 10:59
0

在程序员出现ArgumentNullException  很容易让程序崩溃掉。、

在 水 一 方 | 园豆:1097 (小虾三级) | 2013-03-15 10:14
0

CurrentDomain_UnhandledException 里面用 

while (true)
            {
                if (glExitApp)
                {
                    LogUnhandledException("--------" + strException + "--------");//异常后的处理,否则程序直接关闭
                    return;
                }
                System.Threading.Thread.Sleep(2 * 1000);
            }

小魔1 | 园豆:202 (菜鸟二级) | 2013-07-12 16:56
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册