我需要开发一个多线程应用程序,其中将有多个线程,每个线程都会生成自定义事件日志,需要将其保存在队列中(不是Microsoft MSMQ)。
还将有另一个线程从队列中读取日志数据并操作它,将某些信息保存到文件中。基本上,我们正在实现多生产者、单消费者的范例。
请问有人能提供如何在C++或C#中实现这一点的建议吗?
谢谢,
我需要开发一个多线程应用程序,其中将有多个线程,每个线程都会生成自定义事件日志,需要将其保存在队列中(不是Microsoft MSMQ)。
还将有另一个线程从队列中读取日志数据并操作它,将某些信息保存到文件中。基本上,我们正在实现多生产者、单消费者的范例。
请问有人能提供如何在C++或C#中实现这一点的建议吗?
谢谢,
使用定义在System.Collections.Concurrent
中的BlockingCollection<T>
可以很容易地完成此类操作。
基本上,您需要创建一个队列,以便所有线程都可以访问它:
BlockingCollection<LogRecord> LogQueue = new BlockingCollection<LogRecord>();
每个生产者都向队列中添加项目:while (!Shutdown)
{
LogRecord rec = CreateLogRecord(); // however that's done
LogQueue.Add(rec);
}
而消费者做了类似的事情:
while (!Shutdown)
{
LogRecord rec = LogQueue.Take();
// process the record
}
默认情况下,BlockingCollection
使用 ConcurrentQueue<T>
作为后备存储。 ConcurrentQueue
处理线程同步,而且当尝试取出一个项目时,BlockingCollection
进行非忙等待。也就是说,如果消费者在队列中没有项目的情况下调用 Take
方法,它会进行非忙等待(没有睡眠/自旋),直到有项目可用。
CompleteAdding
方法,这会标记集合为添加完成状态(也就是说,不能再添加更多的元素)。消费者随后就可以使用while (LogQueue.TryTake(out rec, Timeout.Infinite))
语句,这意味着它会清空集合然后退出。当队列为空且集合已经标记为添加完成状态时,TryTake
方法会返回False
。 - Jim MischelCompleteAdding()
,并且还要将Take()
包围在一个 try-catch 结构中,处理 IOE,并且当它发生时什么也不做,只是返回。 - deostrollTask.Run()
调用。或者任何允许你启动线程的东西。你选择什么取决于你在程序的其余部分中使用了什么。 - Jim Mischel