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


    建议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个建议》陆敏技

  • 相关阅读:
    前端神器avalonJS入门(一)
    emmet的使用
    VS2015中SharedProject与可移植类库(PCL)项目
    Map工具系列-08-map控件查看器
    Map工具系列-07-TFS变更集提取工具
    Map工具系列-06-销售营改增历史数据处理工具
    2018.04.02 matplotlib 图名,图例,轴标签,轴边界,轴刻度,轴刻度标签
    2018.03.30 abap屏幕标签保存之前执行过的状态
    2018.03.29 python-matplotlib 图表生成
    2018.03.29 python-pandas 数据读取
  • 原文地址:https://www.cnblogs.com/jesselzj/p/4738081.html
Copyright © 2020-2023  润新知