调用 CompleteAdding() 时如何处理 BlockingCollection<> 中的剩余数据
How to process remaining data in the BlockingCollection<> when CompleteAdding() has been called
BlockingCollection<>
在收到来自 CompleteAdding()
方法的调用时忽略处理底层队列中的剩余数据。以下代码是消费者方法的一部分:
while (blockingCollection.TryTake(out item Item))
{
//Do something with item.
}
相反,我想以一种处理所有剩余项目的方式更改它 AFTER 生产者问题 CompleteAdding()
方法,以及 ONLY THEN 跳出循环。
这不是消耗 BlockingCollection<T>
:
的正确方法
while (blockingCollection.TryTake(out item Item))
{
// Do something with item
}
上面的循环会在 blockingCollection
暂时没有物品的任何时候退出。正确的做法是枚举GetConsumingEnumerable()
:
foreach (var item in blockingCollection.GetConsumingEnumerable())
{
// Do something with item
}
当 blockingCollection
被标记为 CompleteAdding
并且所有可用项目都已处理时,上述循环退出。如果 blockingCollection
在任何时候暂时为空,循环将阻塞当前线程,同步等待新项目或 CompleteAdding()
信号。
下面介绍了一种更专业的循环变体。如果不活动,它会每隔几秒记录一条消息,这样您就知道消费者没有死,只是闲着。
while (true)
{
while (blockingCollection.TryTake(out item Item, TimeSpan.FromSeconds(10)))
{
// Do something with item
}
if (blockingCollection.IsCompleted) break;
// Log a heartbeat
}
BlockingCollection<>
在收到来自 CompleteAdding()
方法的调用时忽略处理底层队列中的剩余数据。以下代码是消费者方法的一部分:
while (blockingCollection.TryTake(out item Item))
{
//Do something with item.
}
相反,我想以一种处理所有剩余项目的方式更改它 AFTER 生产者问题 CompleteAdding()
方法,以及 ONLY THEN 跳出循环。
这不是消耗 BlockingCollection<T>
:
while (blockingCollection.TryTake(out item Item))
{
// Do something with item
}
上面的循环会在 blockingCollection
暂时没有物品的任何时候退出。正确的做法是枚举GetConsumingEnumerable()
:
foreach (var item in blockingCollection.GetConsumingEnumerable())
{
// Do something with item
}
当 blockingCollection
被标记为 CompleteAdding
并且所有可用项目都已处理时,上述循环退出。如果 blockingCollection
在任何时候暂时为空,循环将阻塞当前线程,同步等待新项目或 CompleteAdding()
信号。
下面介绍了一种更专业的循环变体。如果不活动,它会每隔几秒记录一条消息,这样您就知道消费者没有死,只是闲着。
while (true)
{
while (blockingCollection.TryTake(out item Item, TimeSpan.FromSeconds(10)))
{
// Do something with item
}
if (blockingCollection.IsCompleted) break;
// Log a heartbeat
}