Проверка очереди <T>Непрерывно - PullRequest
13 голосов
/ 21 апреля 2011

Я бы хотел, чтобы функция постоянно проверяла Очередь на новые добавления в одном потоке

Очевидно, что есть опция непрерывного цикла со сном, но я хочу что-то менее расточительное.

Я рассмотрел дескриптор ожидания некоторого типа, а затем получил сигнал очереди, но я не могу переопределить Enqueue безопасно, поскольку он не является виртуальным.

Теперь я рассматриваю инкапсуляцию Queue<T> как лучший вариантно я хотел бы спросить вас, ребята, есть ли лучший вариант!

Идея такова: я хочу, чтобы многие потоки имели доступ к сокетному соединению, гарантируя, что они читают только ответ на свое сообщение, поэтому я собиралсяиметь один поток для отправки и чтения ответов, а затем выполнить обратный вызов с данными ответов (в виде простого текста)

1 Ответ

17 голосов
/ 21 апреля 2011

Попробуйте очередь блокировки: Создание очереди блокировки в .NET?

Основная идея заключается в том, что при вызове TryDequeue он будет блокироваться, пока что-то не появится вочередь.Как вы можете видеть, «красота» очереди блокировки заключается в том, что вам не нужно опрашивать / спать или делать что-то сумасшедшее в этом роде… это фундаментальная основа для шаблона «производитель / потребитель».

Моя версияочереди блокировки:

public class BlockingQueue<T> where T : class
{
    private bool closing;
    private readonly Queue<T> queue = new Queue<T>();

    public int Count
    {
        get
        {
            lock (queue)
            {
                return queue.Count;
            }
        }
    }

    public BlockingQueue()
    {
        lock (queue)
        {
            closing = false;
            Monitor.PulseAll(queue);
        }
    }

    public bool Enqueue(T item)
    {
        lock (queue)
        {
            if (closing || null == item)
            {
                return false;
            }

            queue.Enqueue(item);

            if (queue.Count == 1)
            {
                // wake up any blocked dequeue
                Monitor.PulseAll(queue);
            }

            return true;
        }
    }


    public void Close()
    {
        lock (queue)
        {
            if (!closing)
            {
                closing = true;
                queue.Clear();
                Monitor.PulseAll(queue);
            }
        }
    }


    public bool TryDequeue(out T value, int timeout = Timeout.Infinite)
    {
        lock (queue)
        {
            while (queue.Count == 0)
            {
                if (closing || (timeout < Timeout.Infinite) || !Monitor.Wait(queue, timeout))
                {
                    value = default(T);
                    return false;
                }
            }

            value = queue.Dequeue();
            return true;
        }
    }

    public void Clear()
    {
        lock (queue)
        {
            queue.Clear();
            Monitor.Pulse(queue);
        }
    }
}

Большое спасибо Марку Гравеллу за это!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...