Подтвердить что ты не робот

Множество потребителей и запрос на блокировку С#

Я использую .NET 4.0 BlockingCollection для обработки очереди элементов, каждая из которых должна обрабатываться с помощью операции, которая может занимать до секунды для обработки каждого элемента. Эта очередь элементов может быть добавлена ​​разными потоками.

У меня есть несколько вопросов относительно этого а) разрешить нескольким потребителям работать над этим BlockingCollection? Я заметил GetConsumingEnumerable(), который, по-видимому, применим для отдельных потребительских сценариев. Причина наличия нескольких потребителей заключается в том, что обработка через экземпляр именованного канала может обрабатывать до трех из этих элементов за раз, поэтому я думал, что у меня могут быть три потребителя.

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

EDIT:

Основываясь на Jon Skeet, ответьте здесь на несколько примеров кода, чтобы проиллюстрировать несколько потребителей, действующих на BlockingCollection, заполненных одним производителем, причем потребители используют GetConsumingEnumerable():

static BlockingCollection<string> coll = new BlockingCollection<string>();

static void Consume()
{
    foreach (var i in coll.GetConsumingEnumerable())
    {
        Console.WriteLine(String.Format("Thread {0} Consuming: {1}",  Thread.CurrentThread.ManagedThreadId, i));
        Thread.Sleep(1000);
    }
}

static void Main(string[] args)
{
    int item = 0;

    Task.Factory.StartNew(() =>
    {
        while (true)
        {
            coll.Add(string.Format("Item {0}", item++));
            Thread.Sleep(500);
        }
    });

    for (int i = 0; i < 2; i++)
    {
        Task.Factory.StartNew(() => Consume());
    }

    while (true) ;
}

Элементы обрабатываются чередующимся образом между двумя потребителями, работающими на двух разных потоках, например.

Thread 4 Consuming: Item 0
Thread 5 Consuming: Item 1
Thread 4 Consuming: Item 2
Thread 5 Consuming: Item 3
Thread 4 Consuming: Item 4
4b9b3361

Ответ 1

Несколько потребителей могут просто вызывать Take или TryTake одновременно - каждый элемент будет потребляться только одним потребителем.

Однако, я считаю, что GetConsumingEnumerable также будет делать то, что вы хотите. Я считаю, что если каждый вызывающий абонент называет это, каждый из них получит отдельное перечислимое потребление, которое снова будет проверять, что каждый элемент потребляется только один раз. Я не уверен, что происходит, когда очередь становится пустой - я не знаю, будет ли MoveNext() блокировать или возвращает false.

Я действительно не следовал вашему второму вопросу, хотя...