AutoResetEvent não está bloqueando corretamente

Eu tenho um thread, que cria um número variável de threads de trabalho e distribui tarefas entre eles. Isso é resolvido passando os threads umTaskQueue objeto, cuja implementação você verá abaixo.

Esses threads de trabalho simplesmente iteram sobre oTaskQueue objeto que foram dados, executando cada tarefa.

private class TaskQueue : IEnumerable<Task>
{
    public int Count
    {
        get
        {
            lock(this.tasks)
            {
                return this.tasks.Count;
            }
        }
    }

    private readonly Queue<Task> tasks = new Queue<Task>();
    private readonly AutoResetEvent taskWaitHandle = new AutoResetEvent(false);

    private bool isFinishing = false;
    private bool isFinished = false;

    public void Enqueue(Task task)
    {
        Log.Trace("Entering Enqueue, lock...");
        lock(this.tasks)
        {
            Log.Trace("Adding task, current count = {0}...", Count);
            this.tasks.Enqueue(task);

            if (Count == 1)
            {
                Log.Trace("Count = 1, so setting the wait handle...");
                this.taskWaitHandle.Set();
            }
        }
        Log.Trace("Exiting enqueue...");
    }

    public Task Dequeue()
    {
        Log.Trace("Entering Dequeue...");
        if (Count == 0)
        {
            if (this.isFinishing)
            {
                Log.Trace("Finishing (before waiting) - isCompleted set, returning empty task.");
                this.isFinished = true;
                return new Task();
            }

            Log.Trace("Count = 0, lets wait for a task...");
            this.taskWaitHandle.WaitOne();
            Log.Trace("Wait handle let us through, Count = {0}, IsFinishing = {1}, Returned = {2}", Count, this.isFinishing);

            if(this.isFinishing)
            {
                Log.Trace("Finishing - isCompleted set, returning empty task.");
                this.isFinished = true;
                return new Task();
            }
        }

        Log.Trace("Entering task lock...");
        lock(this.tasks)
        {
            Log.Trace("Entered task lock, about to dequeue next item, Count = {0}", Count);
            return this.tasks.Dequeue();
        }
    }

    public void Finish()
    {
        Log.Trace("Setting TaskQueue state to isFinishing = true and setting wait handle...");
        this.isFinishing = true;

        if (Count == 0)
        {
            this.taskWaitHandle.Set();
        }
    }

    public IEnumerator<Task> GetEnumerator()
    {
        while(true)
        {
            Task t = Dequeue();
            if(this.isFinished)
            {
                yield break;
            }

            yield return t;
        }
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }
}

Como você pode ver, estou usando umAutoResetEvent objeto para garantir que os threads de trabalho não saiam prematuramente, ou seja, antes de executar qualquer tarefa.

Em poucas palavras:

o encadeamento principal atribui uma tarefa a um encadeamentoEnqeueue-ing uma tarefa ao seu TaskQueueo encadeamento principal notifica o encadeamento que não há mais tarefas a serem executadas chamando o comando TaskQueueTerminar() métodoo encadeamento do trabalhador recupera a próxima tarefa atribuída a ele, chamando o comando TaskQueueRetirar da fila() método

O problema é que oRetirar da fila() frequentementelança uma InvalidOperationException, dizendo que a fila está vazia. Como você pode ver, eu adicionei alguns registros, e acontece queAutoResetEvent não bloqueia oRetirar da fila (), apesar de não haver chamadas para suaConjunto() método.

Pelo que entendi, chamar AutoResetEvent.Set () permitirá que um thread em espera prossiga (que anteriormente chamava AutoResetEvent.WaitOne ()) e depois chama automaticamente AutoResetEvent.Reset (), bloqueando o próximo garçom.

Então, o que pode estar errado? Eu entendi algo errado? Tenho algum erro em algum lugar? Estou sentado acima disso por 3 horas agora, mas não consigo descobrir o que há de errado. Por favor me ajude!

Muito obrigado!

questionAnswers(3)

yourAnswerToTheQuestion