ThreadPool.QueueUserWorkItem引发的血案,线程池异步非正确姿势导致程序闪退的问题
Posted 天道酬勤,商道酬信。
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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; } } }
处理前后对比
处理前
处理后
以上是关于ThreadPool.QueueUserWorkItem引发的血案,线程池异步非正确姿势导致程序闪退的问题的主要内容,如果未能解决你的问题,请参考以下文章