码迷,mamicode.com
首页 > 编程语言 > 详细

【转】编写高质量代码改善C#程序的157个建议——建议66:正确捕获多线程中的异常

时间:2017-12-06 16:14:10      阅读:151      评论:0      收藏:0      [点我收藏+]

标签:delegate   处理异常   try   cti   row   包装   show   win   方式   

 

建议66:正确捕获多线程中的异常

多线程的异常处理需要采用特殊的方式。一下这种方式会存在问题:

            try
            {
                Thread t = new Thread((ThreadStart)delegate
                {
                    throw new Exception("多线程异常");
                });
                t.Start();
            }
            catch (Exception error)
            {
                MessageBox.Show(error.Message + Environment.NewLine + error.StackTrace);
            }

应用程序并不会在这里捕获线程的异常,而是会直接退出。从.NET2.0开始,任何线程上未处理的异常都会导致应用程序的退出(先会触发APPDomain的UnhandledException)。上面的代码中的try-catch实际上捕获的还是当前线程的异常,而t属于新的异常,所以,正确的做法是:

            Thread t = new Thread((ThreadStart)delegate
            {
                try
                {
                    throw new Exception("多线程异常");
                }
                catch (Exception error)
                {
                    MessageBox.Show("工作线程异常:" + error.Message + Environment.NewLine + error.StackTrace);
                }
            });
            t.Start();

也就是说,新起的线程中异常的捕获,可以将线程内部代码全部try起来。原则上说,每个线程的业务异常应该在自己的内部处理完毕,不过,我们仍然需要一个办法,将线程内部的异常传递到主线程上。

在Windows窗体程序中,可以使用窗体的BeginInvoke方法将异常传递给主窗体线程:

            Thread t = new Thread((ThreadStart)delegate
            {
                try
                {
                    throw new Exception("非窗体线程异常");
                }
                catch (Exception ex)
                {
                    this.BeginInvoke((Action)delegate
                    {
                        throw ex;
                    });
                }
            });
            t.Start();

以上代码会最终引发主线程的Application.ThreadException。

在WPF窗体中,可以这样做:

            Thread t = new Thread((ThreadStart)delegate
            {
                try
                {
                    throw new Exception("非窗体线程异常");
                }
                catch (Exception ex)
                {
                    this.Dispatcher.Invoke((Action)delegate
                    {
                        throw ex;
                    });
                }
            });
            t.Start();

 

不过,除了上面的两种方式,我们更建议使用事件回调的方式将工作线程的异常包装到主线程。用事件回调的方式处理异常的好处是提供了统一的入口进行异常处理。这种方式将在建议85阐述。

 

 

 

转自:《编写高质量代码改善C#程序的157个建议》陆敏技

【转】编写高质量代码改善C#程序的157个建议——建议66:正确捕获多线程中的异常

标签:delegate   处理异常   try   cti   row   包装   show   win   方式   

原文地址:http://www.cnblogs.com/farmer-y/p/7992881.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!