@ Ответ Джои связан с исходным кодом и дал правильный результат, но проблема немного более тонкая.
BC.Take
вызывает BC.TryTake
( не на базовом коллекция). BC.TryTake
затем ждет семафор. Этот семафор увеличивается, когда элемент добавляется в B C.
. Затем он вызывает Underlying.TryTake
и броски напрямую, если возвращается false . Сокращенно:
//If an item was successfully removed from the underlying collection.
removeSucceeded = m_collection.TryTake(out item);
if (!removeSucceeded) {
// Check if the collection is empty which means that the collection was modified outside BlockingCollection
throw new InvalidOperationException (SR.GetString(SR.BlockingCollection_Take_CollectionModified));
}
Это единственное место, где Underlying.TryTake
вызывается в B C.
Так что TryTake
действительно никогда не может потерпеть неудачу. Однако гарантируется (текущим кодом B C), что TryTake
вызывается только после соответствующего TryAdd
. Поэтому базовой структуре данных просто необходимо убедиться, что операции TryTake
никогда не задерживаются после окончания операций TryAdd
, поскольку B C не будет пытаться TryTake
, пока TryAdd
единственного элемент все еще выполняется .