.NET Consumer/Producer (очередь)

Я новичок в .NET/Threads и хотел бы знать, может ли кто-нибудь помочь мне в этом упражнении. Мне нужно заменить комментарии, чтобы заставить его работать без блокировки потоков:

private Queue<int> queue;

public void ConsumeFunc(){
    while (true){
        // 1
        while (/* 2 */){
        // 3
        }
        int element = queue.Dequeue();
        // 4
        Console.WriteLine("Consume element: " + element);
        Thread.Sleep(new Random((int)DateTime.Now.Ticks).Next(0, 2) * 1000);
    }
}

private void ProduceFunc(){
    while (true) {
        // 1
        queue.Enqueue(DateTime.Now.Millisecond);
        // 2
        // 3
        Thread.Sleep(new Random((int)DateTime.Now.Ticks).Next(0, 2) * 1000);
    }
}

мне удалось это сделать, но это не завершено

public void ConsumerFunc(){
    while (true){
        Monitor.PulseAll(queue);    // 1
        while (queue.Count == 0){   /* 2 */
            Monitor.Wait(queue);    // 3
        }
        int element = queue.Dequeue();
        lock (queue)    // 4
        Console.WriteLine("Consume element: " + element);
        Thread.Sleep(new Random((int)DateTime.Now.Ticks).Next(0, 2) * 1000);
    }
}


public void ProducerFunc(){
    while (true) {
        lock (queue)    // 1
        queue.Enqueue(DateTime.Now.Millisecond);
        Monitor.PulseAll(queue);    // 2
        // 3 ???
        Thread.Sleep(new Random((int)DateTime.Now.Ticks).Next(0, 3) * 1000);
    }
}

и выдает следующую ошибку: Метод синхронизации объектов был вызван из несинхронизированного блока кода, Monitor.PulseAll(queue);


person Dany    schedule 27.12.2011    source источник
comment
+1 за демонстрацию попытки решить проблему, прежде чем обращаться за помощью. Действительно аккуратно поставленный вопрос!   -  person André Caron    schedule 27.12.2011


Ответы (1)


Вместо того, чтобы пытаться реализовать синхронизацию самостоятельно, взгляните на BlockingCollection. Он выполняет всю синхронизацию за вас и будет работать лучше, чем все, что вы можете создать, используя класс Queue и Monitor.

Существует множество примеров в документации по .NET, здесь, в Stack Overflow, и в других местах. Моя статья может оказаться полезной: http://www.informit.com/guides/content.aspx?g=dotnet&seqNum=821

person Jim Mischel    schedule 27.12.2011
comment
Если целью является создание очереди, вы также можете использовать ConcurrentQueue: msdn .microsoft.com/en-us/library/dd267265.aspx - person Mathias; 27.12.2011
comment
@Mathias: BlockingCollection — это более общий интерфейс, который по умолчанию использует ConcurrentQueue в качестве резервного хранилища. Я еще не сталкивался со случаем, когда лучше использовать ConcurrentQueue отдельно. - person Jim Mischel; 27.12.2011