Несколько производителей, один потребитель

Мне нужно разработать многопоточное приложение, в котором будет несколько потоков, каждый поток создает собственный журнал событий, который необходимо сохранить в очереди (не Microsoft MSMQ).

Будет другой поток, который считывает данные журнала из очереди и манипулирует ими, с определенной информацией для сохранения информации журнала в файл. В основном здесь мы реализуем парадигму с несколькими производителями, с одним потребителем.

Кто-нибудь может дать предложения о том, как реализовать это в C++ или С#.

Спасибо,

Ответ 1

Это очень легко сделать, используя BlockingCollection<T>, определенный в System.Collections.Concurrent.

В принципе, вы создаете свою очередь, чтобы все потоки могли получить к ней доступ:

BlockingCollection<LogRecord> LogQueue = new BlockingCollection<LogRecord>();

Каждый производитель добавляет элементы в очередь:

while (!Shutdown)
{
    LogRecord rec = CreateLogRecord(); // however that done
    LogQueue.Add(rec);
}

И потребитель делает что-то подобное:

while (!Shutdown)
{
    LogRecord rec = LogQueue.Take();
    // process the record
}

По умолчанию BlockingCollection использует ConcurrentQueue<T> в качестве хранилища резервных копий. ConcurrentQueue выполняет синхронизацию потоков, а BlockingCollection выполняет ожидание при попытке взять элемент. То есть, если потребитель вызывает Take, когда в очереди нет элементов, он делает незанятое ожидание (без спящего/вращающегося) до тех пор, пока элемент не будет доступен.

Ответ 3

То, что вы планируете, представляет собой классическую очередь потребителей производителей с потоком, потребляющим элементы в очереди, чтобы выполнить некоторую работу. Это может быть завернуто в конструкцию более высокого уровня, называемую "актером" или "активным объектом".

В основном это обертывает очередь и поток, который потребляет элементы в один класс, а остальные - все асинхронные методы в этом классе, которые помещают сообщения в очередь, выполняемые потоком актера. В вашем случае класс может иметь один метод writeData, который хранит данные в очереди и запускает переменную условия, чтобы уведомить поток актора о том, что в очереди есть что-то. Поток актера видит, есть ли какие-либо данные в очереди, если не ждет переменная условия.

Вот хорошая статья о концепции:

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

Ответ 4

Несколько производителей, один потребитель - самый простой сценарий для многопоточной передачи очереди. Потоковая очередь может быть реализована как комбинация переменной condition/mutex и std:: queue (добавьте cv, если вы хотите обрабатывать всю очередь).

Пользователь ждет на cv, пока очередь пуста. сигнал производителей при добавлении в очередь (отправка).