短信平臺記錄日誌模塊,是經過異步方式來記錄的,即日誌工具類裏初始化一個Queue對象,公共的寫日誌方法的處理邏輯是把日誌消息放到Queue裏。構造器裏設定一個死循環,不停的讀隊,而後把日誌消息持久化到磁盤的文本文件裏。html
構造方法的代碼以下:異步
public Log() { //開啓線程負責將日誌寫入到指定地點 ThreadPool.QueueUserWorkItem(o => { try { while (true) { if (_messageQueue.Count > 0) { lock (_messageQueue) { while (_messageQueue.Count > 0) { LogMessage logMessage = _messageQueue.Dequeue(); WriteFile(logMessage); } } } else { Thread.Sleep(300); } } } catch (Exception ex) { LogMessage log = new LogMessage() { Content = "構造器執行報錯:" + ex.ToString() }; FileHelper.WriteFile(string.Format(@"{0}\{1:yyyy-MM-dd}-LOGERROR.txt", _logPath, DateTime.Now), log.GetFormattedLog()); } }); }
近期經過看線上站點日誌,發現不按期會有ThreadAbortException被捕獲,分佈式
時間:2016-08-02 10:23:01 構造器執行報錯:System.Threading.ThreadAbortException: 正在停止線程。 在 System.Threading.Thread.SleepInternal(Int32 millisecondsTimeout) 在 Common.Log.<.ctor>b__1(Object o) ------------------------------------------------------------------------------- 時間:2016-08-02 10:47:32 構造器執行報錯:System.Threading.ThreadAbortException: 正在停止線程。 在 System.Threading.Thread.SleepInternal(Int32 millisecondsTimeout) 在 Common.Log.<.ctor>b__2(Object o) ----------------------------------------------------------------------------------------
經過分析,當站點應用程序池回收或遇到其餘未捕獲的異常時,線程會被Abort,這時,當線程裏的代碼再被執行時,就會拋出ThreadAbortException異常。模塊化
微軟官方對ThreadAbortException的介紹:工具
在調用 Abort 方法以銷燬線程時,CLR將引起ThreadAbortException。ThreadAbortException 是一種可捕獲的特殊異常,但在 catch 塊的結尾處它將自動被再次引起。引起此異常時,運行庫將在結束線程前執行全部 finally 塊。因爲線程能夠在 finally 塊中執行未綁定計算,或調用 Thread.ResetAbort 來取消停止,因此不能保證線程將徹底結束。若是您但願一直等到被停止的線程結束,能夠調用 Thread.Join 方法。Join 是一個模塊化調用,它直到線程實際中止執行時才返回。性能
下面的示例說明如何停止線程。接收 ThreadAbortException 的線程使用 ResetAbort 方法取消停止請求並繼續執行。spa
using System; using System.Threading; using System.Security.Permissions; public class ThreadWork { public static void DoWork() { try { for(int i=0; i<100; i++) { Console.WriteLine("Thread - working."); Thread.Sleep(100); } } catch(ThreadAbortException e) { Console.WriteLine("Thread - caught ThreadAbortException - resetting."); Console.WriteLine("Exception message: {0}", e.Message); Thread.ResetAbort(); } Console.WriteLine("Thread - still alive and working."); Thread.Sleep(1000); Console.WriteLine("Thread - finished working."); } } class ThreadAbortTest { public static void Main() { ThreadStart myThreadDelegate = new ThreadStart(ThreadWork.DoWork); Thread myThread = new Thread(myThreadDelegate); myThread.Start(); Thread.Sleep(100); Console.WriteLine("Main - aborting my thread."); myThread.Abort(); myThread.Join(); Console.WriteLine("Main ending."); } }
運行結果:線程
Thread - working. Main - aborting my thread. Thread - caught ThreadAbortException - resetting. Exception message: Thread was being aborted. Thread - still alive and working. Thread - finished working. Main ending.
————————————————————–我是萌萌噠分界線————————————————————日誌