随笔-20  评论-140  文章-22  trackbacks-0
为了增强现在正在开发的系统的健壮性,需要捕获运行时出现的无法预料而且没有被处理(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 阅读(2287) 评论(8)  编辑 收藏 网摘 所属分类: ALEIS 设计

评论:
#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
  回复  引用    

标题  
姓名  
主页
Email (博主才能看到) 
验证码 *  看不清,换一张 [登录][注册]
内容(请不要发表任何与政治相关的内容)  
  登录  使用高级评论  新用户注册  返回页首  恢复上次提交      
"五向定位"职业成长路线公开课(上海、南京、大连)
Google站内搜索


相关链接: