使用GetConsumingEnumerable进行BlockingCollection

时间:2014-05-08 03:23:33

标签: multithreading c#-4.0 concurrency

我正在使用BlockingCollection插入一些使用某些线程处理的值。

有时候我必须拍摄这个集合的“快照”来检查一些结果..所以我这样做:

IEnumerable<SourceResult> response = m_response.GetConsumingEnumerable();
IEnumerable<string>       results  = response.Where(i => i.source == "TEST1" || i.source == "TEST2").Select(i => i.json).DefaultIfEmpty(null);

if (results != null && results.Count() > 0)
{
    // CODE
}

当代码到达此IF语句时,应用程序冻结。

为什么呢?似乎响应永远被锁定。

有什么想法吗?我做错了什么?

非常感谢!

1 个答案:

答案 0 :(得分:2)

.GetConsumingEnumerable()生成&#34;阻止&#34;枚举该集合的名称来自。简而言之,您使用的是错误的集合。

使用BlockingCollection的方法是在其上放置一个线程来运行循环。

foreach(var item in blockingCollection.GetConsumingEnumerable())
{
    //do some work
}

然后使用其他线程将对象放置到阻塞集合上。它被称为&#34;阻止收集&#34;因为它的枚举器在命中最后一个对象时会阻塞(休眠),然后等待一个新项目添加到列表中。

每个循环的唯一出路是在阻塞集合上调用.CompleteAdding()。由于IEnumerable.Count()仅生效......

var count = 0;
foreach(var item in list)
{
   count++;
}
return count;

您的代码在if语句中的foreach循环上阻塞(等待您调用.CompleteAdding())。

我怀疑你实际上想要更像ConcurrentBag的东西。