Возможно, вы сможете использовать очереди, чтобы помочь вам с блокировками вокруг них. Производитель работает над чем-то, производит его и помещает в вспомогательную очередь. Помощник берет его, делает с ним что-то, а затем помещает его в очередь потребителей. Потребитель берет его, потребляет его и продолжает.
Что-то вроде этого:
Queue<MyDataType> helperQ, consumerQ;
object hqLock = new object();
object cqLock = new object();
// producer thread
private void ProducerThreadFunc()
{
while(true)
{
MyDataType data = ProduceNewData();
lock(hqLock)
{
helperQ.Enqueue(data);
}
}
}
// helper thread
private void HelperThreadFunc()
{
while(true)
{
MyDataType data;
lock(hqLock)
{
data = helperQ.Dequeue();
}
data = HelpData(data);
lock(cqLock)
{
consumerQ.Enqueue(data);
}
}
}
// consumer thread
private void ConsumerThreadFunc()
{
while(true)
{
MyDataType data;
lock(cqLock)
{
data = consumerQ.Dequeue();
}
Consume(data);
}
}
ПРИМЕЧАНИЕ: Вам нужно будет добавить больше логики в этом примере, чтобы убедиться, годны к употреблению. Не ожидайте, что он будет работать как есть. В основном, используйте сигналы для одного потока, чтобы другие знали, что данные доступны в его очереди (или, как наихудший опрос, размер очереди, чтобы убедиться, что он больше 0, если он равен 0, затем спящий - но сигналы более чистые и более эффективные).
Этот подход позволит обрабатывать данные с разной скоростью (что может привести к проблемам с памятью).
, обратите внимание, что в некоторых условиях несколько потоков могут находиться в рабочем состоянии (то есть многопроцессорная система и данные в процессе). – Adriaan