C# 中的 AutoResetEvent 關鍵字

在工做的任務中,須要對客戶端和服務端 通訊包進行落地。把這個作成通用的模塊,在高併發和多線程下,也可以工做。算法

在查閱了大衆化日誌方案後,決定採用:寫日誌和寫文件分離的方式進行。大概內容圖:安全

log.png

須要記錄是通訊包,將須要記錄的通訊包推送到隊列,再由一個專門的線程去讀取隊列,將出隊列的數據寫到文件中。這樣將每次直接IO瓶頸,轉化成存儲隊列的大小,瓶頸變成了內存的大小。上代碼:bash

// 掃描隊列,寫文件的線程
private static readonly Thread LogThread;

// 自定義線程安全的Queue
private static readonly ConcurrentQueue<Message> LogQueue; 

// 多線程下,操做統一資源的鎖
private static readonly object SyncRoot;

// 在隊列沒有數據時,線程中止掃描標誌
private static readonly AutoResetEvent AutoReset = null; 
複製代碼
// 構造函數
static Utils()
{
   AutoReset = new AutoResetEvent(false);
   SyncRoot = new object();
   LogThread = new Thread(WriteLog);
   LogQueue = new ConcurrentQueue<Message>();
   LogThread.Start();
}
複製代碼
// 記錄日誌
public static void Log(List<Message> msg)
{
  foreach (var item in msg)
  {
      // 隊列入隊
      LogQueue.Enqueue(item);
   }
   // 激活掃描中止的線程(發出信號)
   AutoReset.Set();
}
複製代碼
// 寫入日誌
private static void WriteLog()
{
   var list = new List<Message>();
   while (true)
   {
   	  // 若是隊列中有數據
      if (LogQueue.Count() > 0)
      {
         IT2ESBMessage _msg;
         // 出隊列
         LogQueue.TryDequeue(out _msg);
         if (_msg!=null)
         {
            list.Add(_msg);
         }
      }
      else
      {
          if (list.Count>0)
          {
              // 加鎖,在多線程操做的時候,保證安全
              lock (SyncRoot)
              {
                  foreach (var item in list)
                  {
                      ProcessWriteLog(item); 
                   }    
               }
               ist.Clear();
            }
            // 在這裏,線程會被暫停,直到收到信號;
            AutoReset.WaitOne();
          }
      }
}
複製代碼
// 寫文件
private static void ProcessWriteLog(Message msg)
{
   try
   {
      FileStream fs;
      fs = new FileStream(_fileName, FileMode.Append, FileAccess.Write);
      //TODO,進行對文件的寫操做,省略一萬字     
   }
   catch (Exception ex)
   {
      Debug.WriteLine(string.Format("寫入日誌失敗,緣由:{0}", ex.Message));
   }
}
複製代碼

AutoResetEvent 關鍵字多線程

  • Reset ():將事件狀態設置爲非終止狀態,致使線程阻止;併發

  • Set ():發送信號到等待線程以繼續其工做;函數

有點相似於計算機中的信號量,回顧《操做系統》中的信號量吧,什麼銀行家算法,什麼信號量已經忘得一乾二淨了。高併發

信號量 用在多線程多任務同步的,一個線程完成了某一個動做就經過信號量告訴別的線程,別的線程再進行某些動做。ui

互斥鎖 是用在多線程多任務互斥的,一個線程佔用了某一個資源,那麼別的線程就沒法訪問,直到這個線程unlock,其餘的線程纔開始能夠利用這個資源spa

相關文章
相關標籤/搜索