zoukankan      html  css  js  c++  java
  • 【转】编写高质量代码改善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个建议》陆敏技

  • 相关阅读:
    .NET 操作XML
    C#常用操作类库五(电脑操作类)
    C#常用操作类库四(File操作类)
    C#常用操作类库一(验证类)
    RabbitMQ 学习
    redis 常用命令
    windows10配置redis一主二从三哨兵
    Oracle递归查询(查询当前记录所有父级或子级)
    echarts 中 柱图 、折线图、柱图层叠
    简单的前台登录
  • 原文地址:https://www.cnblogs.com/farmer-y/p/7992881.html
Copyright © 2011-2022 走看看