BlockingCollection TryTake возвращает ложь вместо блока, когда коллекция пуста - PullRequest
0 голосов
/ 23 мая 2018

Я получаю ложное значение от метода TryTake BlockingCollection, когда BlockingCollection пусто, хотя ожидаемое поведение заключается в блокировке, пока коллекция не заполнится.

Примечаниечто коллекция не ограничена верхним пределом (что должно повлиять на TryAdd, а не на TryTake) и что время ожидания, установленное для операции добавления, не прошло.

Вот моя оболочка вокруг объекта BlockingCollection:

    public T TryTake(int timeoutMiliseconds)
    {
        var result = default(T);

        if (!_collection.TryTake(out result, timeoutMiliseconds))
        {
            throw new InvalidOperationException("Unable to get item from collection.");
        }

        return result;
    }

Есть идеи, что может вызвать это?

Я реализовал шаблон Producer-Consumer, основанный на этой статье: Многопоточная обработка шаблона проектирования SqlDataReader - Producer / Consumer

1 Ответ

0 голосов
/ 23 мая 2018

Я наконец понял, что, как показывает этот SO post , я получил ложное из TryTake, потому что коллекция была очищена, а также помечена мной как завершенная (вызвав метод CompleteAdding() дляколлекция).

Итак, чтобы решить эту проблему, я добавил условие к завершенному флагу.

Можно утверждать, что TryTake никогда не вернет false в то время как установленный флаг равен false .Я не уверен, что это всегда правильно, поэтому я предпочитаю выдавать ошибку в этом случае.

    public T TryTake(int timeoutMiliseconds)
    {
        var result = default(T);

        if (!_collection.TryTake(out result, timeoutMiliseconds) 
            && !_collection.IsAddingCompleted)
        {
            throw new InvalidOperationException("Unable to get item from collection.");
        }

        return result;
    }

Обратите внимание, что крайне важно сначала поставить вызов TryTake, а затем IsAddingCompleted.В противном случае первое условие может пройти, и вы сразу заблокируете TryTake.

...