如何清空BlockingCollection

Jon*_*Jon 15 .net c# .net-4.0 task-parallel-library c#-4.0

我有一个线程添加项目到BlockingCollection.

在我正在使用的另一个线程上 foreach (var item in myCollection.GetConsumingEnumerable())

如果有问题我想要摆脱我的foreach和我的方法并清除剩下的东西,BlockingCollection但是我找不到办法去做.

有任何想法吗?

Pao*_*tti 17

我正在使用这种扩展方法:

public static void Clear<T>(this BlockingCollection<T> blockingCollection)
{
    if (blockingCollection == null)
    {
        throw new ArgumentNullException("blockingCollection");
    }

    while (blockingCollection.Count > 0)
    {
        T item;
        blockingCollection.TryTake(out item);
    }
}
Run Code Online (Sandbox Code Playgroud)

我想知道是否有一个更好,更少hacky的解决方案.

  • 使用新的`out var`语法:`while(blockingCollection.TryTake(out var _)){}` (3认同)
  • @Assimilater在`while`检查和`TryTake`之间存在竞争条件.例如,另一个线程可以取出最后一个元素,而`Take`会引发一个`InvalidOperationException`. (2认同)
  • 类似于 Kjellski 的评论,但不需要新语法,这可以缩短为 `T _; while (blockingCollection.TryTake(out _)){}` (2认同)

myt*_*thz 11

只需取出所有剩余物品:

while (collection.TryTake(out _)){}
Run Code Online (Sandbox Code Playgroud)


Jon*_*eet 8

可能使用过载GetConsumingEnumerable需要a CancellationToken,然后如果生产方出现任何问题,它可以取消消费者.

  • 对于粗心的,"GetConsumingEnumerable"的注释将在集合为空(等待更多条目)时阻止,除非您之前调用过"CompleteAdding".它位于示例代码块中,但未在方法说明中提及. (3认同)

cli*_*cky 5

这对我有用

while (bCollection.Count > 0)
{
    var obj = bCollection.Take();
    obj.Dispose();
}
Run Code Online (Sandbox Code Playgroud)

Take() 从集合中删除,您可以调用对象的任何清理,并且循环条件不会调用任何阻塞调用.