随笔-21  评论-141  文章-26  trackbacks-0

C#中unhandled异常处理的问题

为了增强现在正在开发的系统的健壮性,需要捕获运行时出现的无法预料而且没有被处理(unhandled)的异常。查了资料后,找到了使用 Application.ThreadException 事件处理这些异常的方法,基本步骤包括,
1、为ThreadException事件添加一个处理异常的函数句柄
2、定义处理异常的函数
例子如下: 
[STAThread]

static
void Main() {   Application.ThreadException += new ThreadExceptionEventHandler(Application_ThreadException);   Application.Run(new FrmMain()); } private static void Application_ThreadException(object sender, ThreadExceptionEventArgs e) {   MessageBox.Show("Unhandled exception: "+e.Exception.ToString()); }
这种方法简单易行,而且处理效率较高,可以按照用户的意图,很方便的添加处理异常理的其他功能。但我发现,如果使用第三方提供的控件时,根本不起作用,原应可能是第三方控件运行在不同的线程中。在Microsoft的帮助中也确实提到了,上面的方法只能处理主线程中未处理的异常。好了,上网查,找到了下面的方法,使用 AppDomain.UnhandledException 替代Application.ThreadException
首先需要了解的是,此时定义的事件处理函数需要在抛出异常的线程中执行,但是在主线程中给出异常提示都是在主线程中完成的,那么如何解决这个问题呢?下面的代码给出了一个比较完整的解决方案。
 
private delegate void ExceptionDelegate(Exception x);

static private FrmMain _MainForm;

///
<summary>
///
The main entry point for the application.
/// </summary>
[STAThread]
static
void Main()
{
  _MainForm = new FrmMain();
  AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(AppDomain_UnhandledException);
  Application.Run(_MainForm);
}

private static void AppDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
  Exception exception;

  exception = e.ExceptionObject as Exception;
  if (exception == null)
{
// this is an unmanaged exception, you may want to handle it differently
   return;
}
  PublishOnMainThread(exception);
}

private static void PublishOnMainThread(Exception exception)
{
  if (_MainForm.InvokeRequired)
  {
    // Invoke executes a delegate on the thread that owns _MainForms's underlying window handle.
    _MainForm.Invoke(new ExceptionDelegate(HandleException), new object[] {exception});
  }
  else
  {
    HandleException(exception);
  }
}

private static void HandleException(Exception exception)
{
  if (SystemInformation.UserInteractive)
  {
    using (ThreadExceptionDialog dialog = new ThreadExceptionDialog(exception))
    {
      if (dialog.ShowDialog() == DialogResult.Cancel)
        return;
    }
    Application.Exit();
    Environment.Exit(0);
  }
}

private void ThreadMethod()
{
  throw new Exception("From new thread");
}

private void button1_Click(object sender, System.EventArgs e)
{
  Thread thread;
  thread = new Thread(new ThreadStart(ThreadMethod));
  thread.Start();
}
需要注意的是:
1、需要为所有的 AppDomain UnhandledException 添加一个处理
2、 UnhandledExceptionEventArgs 参数中包含一个 IsTerminating 属性,表示是否中止 common language runtime
posted on 2005-08-12 09:08 .3S Swimmer 阅读(2973) 评论(8) 编辑 收藏

评论:
#1楼 2005-08-12 11:41 | 柚子Nan      
太好了,正找这个呢!
你有没有办法不让第三方控件中的MessagBox弹出来?

 回复 引用 查看   
#2楼 2005-08-12 18:42 | yinh      
嗯,不错,以前看webcast的时候就知道,工作线程的异常(以及其它任何工作线程要更新主线程的界面元素动作),都要用主线程来调用。通过一个委托,然后判断界面线程中的任何一个控件的InvokeRequired,实现方法上面楼主已经大致写了。不过今天又学到一个新知识:AppDomain.UnhandledException中统一调用,不错,谢谢楼主。
 回复 引用 查看   
#3楼 2005-08-24 20:33 | YuL      
嘿嘿,我不得不告诉你,你已经被我选为传染对象,并对你开始进行注入毒液。。。
到这里看一下吧↓
http://yul.cnblogs.com/archive/2005/08/24/222076.html

 回复 引用 查看   
#4楼 2006-06-09 18:07 | Bear.sTaR{R}      
不错,不错,正找这个资料,谢谢啦。收藏了
 回复 引用 查看   
#5楼 2006-08-31 15:31 | wydotnet@gmail.com[未注册用户]
我的问题是,debug的时候Application.ThreadException不能触发,但是如果单独运行程序的时候,Application.ThreadException会被触发,我不太明白为什么会有这样的区别?

 回复 引用   
#6楼 2007-04-07 14:20 | 思源[未注册用户]
WebForm也要样吗?
 回复 引用   
#7楼 2007-09-18 16:01 | HEJINGSHENG[未注册用户]
--引用--------------------------------------------------
柚子Nan: 太好了,正找这个呢!
你有没有办法不让第三方控件中的MessagBox弹出来?
--------------------------------------------------------

 回复 引用   
#8楼 2007-09-18 16:01 | HEJINGSHENG[未注册用户]
HAO
 回复 引用   
昵称:.3S Swimmer
园龄:6年11个月
粉丝:6
关注:0
<2005年8月>
31123456
78910111213
14151617181920
21222324252627
28293031123
45678910

搜索

 
 

常用链接

我的标签

随笔分类(23)

随笔档案(22)

文章分类(25)

相册

ALEIS Team

Samplx小组

其他

积分与排名

  • 积分 - 62142
  • 排名 - 1714

最新评论

阅读排行榜

评论排行榜

推荐排行榜