15

我必须开发一个多线程应用程序,其中将有多个线程,每个线程生成需要保存在队列中的自定义事件日志(不是 Microsoft MSMQ)。

将有另一个线程从队列中读取日志数据并对其进行操作,并使用某些信息将日志信息保存到文件中。基本上,我们在这里实现了多生产者、单消费者范式。

任何人都可以就如何在 C++ 或 C# 中实现这一点提供建议。

谢谢,

4

3 回答 3

17

这种事情很容易使用中BlockingCollection<T>定义的System.Collections.Concurrent

基本上,您创建队列以便所有线程都可以访问它:

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使用 aConcurrentQueue<T>作为后备存储。ConcurrentQueue负责线程同步,并且在BlockingCollection尝试获取项目时会进行非忙等待。也就是说,如果消费者Take在队列中没有项目时调用,它会进行非忙等待(无睡眠/旋转),直到有项目可用。

于 2011-02-24T17:49:58.103 回答
2

您正在计划的是一个经典的生产者消费者队列,其中一个线程消耗队列中的项目来做一些工作。这可以包装成一个更高级别的构造,称为“actor”或“active object”。

基本上,这将队列和使用项目的线程包装到一个类中,其他线程在这个类上的所有异步方法都将消息放在队列中以由参与者的线程执行。在您的情况下,该类可能有一个方法 writeData 将数据存储在队列中并触发条件变量以通知参与者线程队列中有东西。如果没有等待条件变量,参与者线程会查看队列中是否有任何数据。

这是一篇关于这个概念的好文章:

http://www.drdobbs.com/go-parallel/article/showArticle.jhtml;jsessionid=UTEXJOTLP0YDNQE1GHPSKH4ATMY32JVN?articleID=225700095

于 2011-02-24T15:39:21.753 回答
2

您可以使用同步队列(如果您有 .NET 3.5 或更早的代码),甚至可以使用新的ConcurrentQueue<T>!

于 2011-02-24T13:39:07.053 回答