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