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;
        }
    }
}

處理前后對比

處理前

處理后


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM