Вместо архитектуры, основанной на событиях, вы можете рассмотреть возможность использования модели производитель / потребитель, аналогичной той, которая у вас уже есть. Но вместо пробуждения через интервал используйте BlockingCollection
в качестве очереди.
Когда транзакция приходит, просто добавьте ее в очередь.
Отдельный поток в вашей программе находится в цикле, который делает TryTake()
из очереди с бесконечным временем ожидания. Всякий раз, когда транзакция добавляется в очередь, этот поток получает и обрабатывает ее, а затем возвращается к следующей. Основной цикл вашего потока обработки будет выглядеть примерно так:
// Initialized at program startup.
BlockingCollection<Transaction> queue = new BlockingCollection<Transaction>();
// In your thread proc
Transaction trans;
while (queue.TryTake(out trans, Timeout.Infinite))
{
// process transaction
}
// Collection is empty
TryTake
- это незанятое ожидание, поэтому он не будет потреблять циклы процессора.
Это должно быть намного проще реализовать, чем система, основанная на событиях, и обеспечить лучшую производительность. Вам также не нужно беспокоиться о слишком большом количестве одновременных событий, вызывающих проблему. Очередь будет буферизовать вещи, чтобы вы могли обрабатывать транзакции как можно быстрее. Это также позволит вам создать несколько потребителей, если вам нужно / нужно.
Пример, по запросу:
Например, возьмите приведенный выше код и поместите его в поток proc:
private void TransactionConsumer()
{
Transaction trans;
while (queue.TryTake(out trans, Timeout.Infinite))
{
// process transaction
}
// Collection is empty
}
Предположим также, что у вас есть какой-то другой метод, который будет добавлять вещи в очередь. Мы назовем это TransactionProducer
. Ваша основная программа запускает три потока: производителя и двух потребителей:
Thread producer = new Thread(TransactionProducer);
Thread consumer1 = new Thread(TransactionConsumer);
Thread consumer2 = new Thread(TransactionConsumer);
producer.Start();
consumer1.Start();
consumer2.Start();
// At this point, you are processing transactions.
// The main thread waits for all threads to exit.
producer.Join();
consumer1.Join();
consumer2.Join();
Обратите внимание, что если метод, который на самом деле обрабатывает транзакции, использует общие ресурсы (например, общий файл журнала), вам придется защищать их с помощью некоторой синхронизации (возможно, блокировки).