美文网首页
C# 中的 AutoResetEvent 关键字

C# 中的 AutoResetEvent 关键字

作者: 梁小生0101 | 来源:发表于2019-03-05 21:25 被阅读0次

在工作的任务中,需要对客户端和服务端 通信包进行落地。把这个做成通用的模块,在高并发和多线程下,也能够工作。

在查阅了大众化日志方案后,决定采用:写日志和写文件分离的方式进行。大概内容图:

log.png

需要记录是通信包,将需要记录的通信包推送到队列,再由一个专门的线程去读取队列,将出队列的数据写到文件中。这样将每次直接IO瓶颈,转化成存储队列的大小,瓶颈变成了内存的大小。上代码:

// 扫描队列,写文件的线程
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 ():发送信号到等待线程以继续其工作;

有点类似于计算机中的信号量,回顾《操作系统》中的信号量吧,什么银行家算法,什么信号量已经忘得一干二净了。

信号量 用在多线程多任务同步的,一个线程完成了某一个动作就通过信号量告诉别的线程,别的线程再进行某些动作。

互斥锁 是用在多线程多任务互斥的,一个线程占用了某一个资源,那么别的线程就无法访问,直到这个线程unlock,其他的线程才开始可以利用这个资源

相关文章

网友评论

      本文标题:C# 中的 AutoResetEvent 关键字

      本文链接:https://www.haomeiwen.com/subject/kxsauqtx.html