【问题标题】:How to process remaining data in the BlockingCollection<> when CompleteAdding() has been called调用 CompleteAdding() 时如何处理 BlockingCollection<> 中的剩余数据
【发布时间】:2021-04-16 11:55:51
【问题描述】:
BlockingCollection<> 在收到来自CompleteAdding() 方法的调用时忽略处理底层队列中的剩余数据。下面的代码,是消费者方法的一部分:
while (blockingCollection.TryTake(out item Item))
{
//Do something with item.
}
相反,我想将其更改为处理所有剩余项目 AFTER 生产者问题 CompleteAdding() 方法,然后 ONLY THEN 从循环。
【问题讨论】:
标签:
c#
multithreading
.net-core
concurrency
producer-consumer
【解决方案1】:
这不是使用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
}