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

  • 相关阅读:
    Flutter开发指南之理论篇:Dart语法05(单线程模型,事件循环模型,Isolate)
    跨平台将终结
    一万字详解 Redis Cluster Gossip 协议
    Java实现简单的计算器
    CSDN开发者周刊第 22期:谷歌 DeepMind 第四代:不学规则就可以玩游戏;图灵奖得主 Edmund Clarke 因感染“新冠”逝世;
    理解Python闭包,这应该是最好的例子
    sscanf函数用法详解
    web项目中配置多个数据源
    web项目中配置多个数据源
    动态表格之查看、删除、编辑
  • 原文地址:https://www.cnblogs.com/jesselzj/p/4738081.html
Copyright © 2011-2022 走看看