Como implemento meu próprio cenário avançado de produtor / consumidor?
NOTA:
fiz um retrabalho completo da minha pergunta. você pode ver a pergunta original através do histórico de alterações.
estou precisando de uma fila "poderosa", que ofereça as seguintes funcionalidades:
Eu tenho um certo escopo para um grupo de objetos. isso significa quegrupo A, Grupo B, ... terão sua própria filaestou preenchendo uma fila em um segmento com escopo de grupoTópico A (Produtor)estou lendo uma fila em um segmento com escopo de grupoLinha B (Consumidor)então terei os seguintes cenários:
existe e não haverá itens na fila (como os trabalhos foram chamados com um "grupo de destino" vazio):Linha B deve escapar do loopatualmente não há nenhum item na fila, poisTópico A está trabalhando no item para enfileirar:Linha B deveria esperarexistem itens na fila:Linha B deve conseguir desenfileirar e processar o itemnão há nenhum item na fila, poisTópico A não tem mais itens para enfileirar:Linha B deve escapar do loopagora eu vim com a seguinte implementação:
public class MightyQueue<T>
where T : class
{
private readonly Queue<T> _queue = new Queue<T>();
private bool? _runable;
private volatile bool _completed;
public bool Runable
{
get
{
while (!this._runable.HasValue)
{
Thread.Sleep(100);
}
return this._runable ?? false;
}
set
{
this._runable = value;
}
}
public void Enqueue(T item)
{
if (item == null)
{
throw new ArgumentNullException("item");
}
this._queue.Enqueue(item);
}
public void CompleteAdding()
{
this._completed = true;
}
public bool TryDequeue(out T item)
{
if (!this.Runable)
{
item = null;
return false;
}
while (this._queue.Count == 0)
{
if (this._completed)
{
item = null;
return false;
}
Thread.Sleep(100);
}
item = this._queue.Dequeue();
return true;
}
}
que então seria usado
Produtor
if (anythingToWorkOn)
{
myFooMightyQueueInstance.Runable = false;
}
else
{
myFooMightyQueueInstance.Runable = true;
while (condition)
{
myFooMightyQueueInstance.Enqueue(item);
}
myFooMightyQueueInstance.CompleteAdding();
}
Consumidor
if (!myFooMightyQueueInstance.Runable)
{
return;
}
T item;
while (myFooMightyQueueInstance.TryDequeue(out item))
{
//work with item
}
mas acredito que essa abordagem está errada, pois estou usando algumasThread.Sleep()
-está lá (não pode haver algum waitHandle ou algo mais?) ... eu também não sou sobre o algo ... alguém pode me ajudar?