Initializes a new instance of the System.Threading.ManualResetEvent
class with a Boolean value indicating whether to set the initial
state to signaled.
ManualResetEvent
是一个线程同步的机制,它可以用于在多个线程之间进行信号通知。通过设置和复位事件,可以实现线程之间的协调和同步。
public static ManualResetEvent FailResetEvent = new ManualResetEvent(initialState: true);
public static void Start()
{
FailResetEvent.Set();
}
public static void Suspend()
{
FailResetEvent.Reset();
}
参看示例
public void TaskService()
{
while (true)
{
//CommonStatic.manualResetEvent.WaitOne();
//await Task.Delay(4000);
if (CommonStatic.loggerQueueData.Count() > 0)
{
try
{
ScanQueue().Wait();
Console.WriteLine("获得排序");
}
catch (Exception ex)
{
continue;
}
}
else
{
Thread.Sleep(4000);
}
}
}
private async Task ScanQueue()
{
while (CommonStatic.loggerQueueData.Count() > 0)
{
try
{
using (var releaser = await m_lock.LockAsync())
{
//从队列中取出
CommonStatic.loggerQueueData.TryDequeue(out string log);
await _Share_DataService.NotificationMessage(log);
}
//取出的queueinfo就可以用了,里面有你要的东西
//以下就是处理程序了
//。。。。。。
}
catch (Exception ex)
{
throw;
}
}
}
ConcurrentQueue
ConcurrentQueue队列是一个高效的线程安全的队列,是Net Framework
4.0,System.Collections.Concurrent命名空间下的一个数据结构。
实现原理
众所周知,在普通的非线程安全队列有两种实现方式:
public static ConcurrentQueue loggerQueueData = new ConcurrentQueue();
1.使用数组实现队列。 2.使用链表实现队列。
看看两种方式的优劣:
.Net Farmework中的普通队列Queue的实现使用了第一种方式,缺点是当队列空间不足会进行扩容,扩容的主要实现是开辟一个原始长度2倍的新数组,然后将原始数组里面的数据复制到新数组中,所以当扩容时就会产生不小的内存开销,在并发的环境中对性能的影响不可小视。当然在调用Queue的构造函数时可以指定默认空间的大小,但是一般情况下数据量是不可预测的,选大了会照成空间浪费,选小了会有复制内存的开销,而且队列扩容以后需要显示调用TrimToSize()方法才能回收掉不使用的内存空间。
第二种链表实现方式虽然消除了空间浪费的问题但是又增加了GC的压力,当入队时会分配一个新节点,出队时要对该节点进行废弃,对于大量的出队入队操作时该实现方式性能不高。
综合以上两种实现方式,在支持多线程并发出队并发入队的情况下,ConcurrentQueue使用了分段存储的概念(如上图所示),ConcurrentQueue分配内存时以段(Segment)为单位,一个段内部含有一个默认长度为32的数组和执行下一个段的指针,有个和Head和Tail指针分别指向了起始段和结束段(这种结构有点像操作系统的段式内存管理和页式内存管理策略)。这种分配内存的实现方式不但减轻的GC的压力而且调用者也不用显示的调用TrimToSize()方法回收内存(在某段内存为空时,会由GC来回收该段内存)。
Segment内部和用数组实现的普通队列相当,只不过对于入队和出队操作使用了原子操作来防止多线程竞争问题,使用随机退让等技术保证活锁等问题,实现机制和ConcurrentStack差别不大,跟多TryAppend的实现细节在源码注释中已经阐述的非常清楚这里就再做不过多的解释。
主要成员函数
入队(EnQueue) 、出队(TryDequeue) 、是否为空(IsEmpty)、获取队列内元素数量(Count)。