• ThreadPool.QueueUserWorkItem引发的血案,线程池异步非正确姿势导致程序闪退的问题


     ThreadPool是.net System.Threading命名空间下的线程池对象。使用QueueUserWorkItem实现对异步委托的先进先出有序的回调。如果在回调的方法里面发生异常则应用程序会出现闪退。当然是指不处理那个异常的情况下。这不公司的CMS在生产环境频频出现闪退的情况。该死的是,原来用老机器配置不高的情况下没有出现过。换了更好的新机器后出现的。

            //
            // 摘要:
            //     将方法排入队列以便执行,并指定包含该方法所用数据的对象。此方法在有线程池线程变得可用时执行。
            //
            // 参数:
            //   callBack:
            //     System.Threading.WaitCallback,它表示要执行的方法。
            //
            //   state:
            //     包含方法所用数据的对象。
            //
            // 返回结果:
            //     如果此方法成功排队,则为 true;如果未能将该工作项排队,则引发 System.NotSupportedException。
            //
            // 异常:
            //   T:System.NotSupportedException:
            //     承载公共语言运行时 (CLR) 的宿主不支持此操作。
            //
            //   T:System.ArgumentNullException:
            //     callBack 为 null。
            [SecuritySafeCritical]
            public static bool QueueUserWorkItem(WaitCallback callBack, object state);
    

    经过一番测试重新了故障现象,但由于是生产环境代码不好大动,看来解决方案就是吞掉异常,让程序不再闪退一种解决办法了。

    编码测试过程

    using System;
    using System.Threading;
    
    namespace ConsoleShell3
    {
        //164-184
        class Program
        {
            static object queueObj = new object();
            static CoreThreadPool pool = new CoreThreadPool();
            static void Main(string[] args)
            {            
                Console.WriteLine("Main Thread OK...");
                pool.Exceute += Pool_Exceute;
                pool.Start();
                pool.Post(queueObj);
                Thread thread = new Thread(() => 
                {
                    while (true)
                    {
                        Thread.Sleep(1000);
                        queueObj = (object)DateTime.Now.Ticks;
                        Console.WriteLine(DateTime.Now);
                        pool.Post(queueObj);
                    }               
                });
                thread.Start();
                Console.ReadLine();
            }
    
            private static void Pool_Exceute(object obj)
            {
                ThreadPool.QueueUserWorkItem(CallbackDemoViod, obj);                      
            }
    
            /// <summary>
            /// 我的方案就是在这里把这个回调的方法用try catch包裹起来,吞到出现的异常
            /// </summary>
            /// <param name="obj"></param>
            private static void CallbackDemoViod(object obj)
            {
                try
                {
                    var inObj = obj;
                    var ex = new Exception("!!!!");
                    throw ex;
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex);
                }
                //以下不catch异常就会导致闪退
                //var inObj = obj;
                //var ex = new Exception("!!!!");
                //throw ex;
            }
        }
    }
    

    处理前后对比

    处理前

    处理后

  • 相关阅读:
    牛人对IC验证的独特理解(转载)
    soc验证扫盲(转载)
    .vimrc
    matchit匹配
    格式化verilog/systemverilog代码插件
    gvim plugin管理
    .alias
    .cshrc
    get_result --perl
    run_regress --perl
  • 原文地址:https://www.cnblogs.com/datacool/p/datacool_CMS_threadpool.html
Copyright © 2020-2023  润新知