C# 中的 AutoResetEvent关键字

Posted by 梁小生 on 2019-03-05

C# 中的 AutoResetEvent 关键字

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

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

log

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

1
2
3
4
5
6
7
8
9
10
11
// 扫描队列,写文件的线程
private static readonly Thread LogThread;

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

// 多线程下,操作统一资源的锁
private static readonly object SyncRoot;

// 在队列没有数据时,线程停止扫描标志
private static readonly AutoResetEvent AutoReset = null;
1
2
3
4
5
6
7
8
9
// 构造函数
static Utils()
{
AutoReset = new AutoResetEvent(false);
SyncRoot = new object();
LogThread = new Thread(WriteLog);
LogQueue = new ConcurrentQueue<Message>();
LogThread.Start();
}
1
2
3
4
5
6
7
8
9
10
11
// 记录日志
public static void Log(List<Message> msg)
{
foreach (var item in msg)
{
// 队列入队
LogQueue.Enqueue(item);
}
// 激活扫描停止的线程(发出信号)
AutoReset.Set();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
// 写入日志
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();
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 写文件
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,其他的线程才开始可以利用这个资源