Я не знаю, как долго будут выполняться ваши задачи, но, похоже, лучше всего было бы использовать ThreadPool.
Кроме того, я бы использовал и фактически использовал только одну центральную очередь - это само по себе устранит некоторую сложность.
У меня есть один поток, который обрабатывает очередь и выполняет действие с элементом, в вашем случае это было бы поставить задачу в очередь.
Что касается обеспечения безопасности потока в очереди, в System.Collections.Concurrent есть ConcurrentQueue для этой цели ( msdn , тест по сравнению с очередью блокировки ).
Теперь добавьте BlockingCollection ( msdn ), и у вас есть все, что вам нужно.
BlockingCollection<Packet> sendQueue = new BlockingCollection<Packet>(new ConcurrentQueue<Packet>());
while (true)
{
var packet = sendQueue.Take(); //this blocks if there are no items in the queue.
ThreadPool.QueueUserWorkItem(state =>
{
var data = (Packet)state;
//do whatever you have to do
}, packet );
}
и где-то есть что-то, что sendQueue.Add(packet);
Подводя итог,
- Одна очередь для всех «рабочих»
- Один поток, который исключает из очереди
и передает его в ThreadPool.
Я думаю, что это так.
ps: если вам нужно контролировать количество потоков, используйте «Smart Thread Pool», как предложено josh3736