4

我现在开始与 TPL 合作。我在这个视频中看到了一个使用 TPL 的简单版本的生产者/消费者模型。

这是问题所在:

以下代码:

BlockingCollection<Double> bc = new BlockingCollection<Double>(100);
IEnumerable<Double> d = bc.GetConsumingEnumerable();

返回IEnumerable<Double>可以使用 foreach 迭代(并自动使用)的:

foreach (var item in d)
{
    // do anything with item
    // in the end of this foreach,
    // will there be any items left in d or bc? Why?
}

我的问题是:

  1. 如果我得到IEnumerator<Double> dEnum = d.GetEnumerator()from (例如,用循环d迭代)也会消耗列表吗?(我的回答:我不这么认为,因为 the 与没有联系,如果你明白我的意思的话。所以它会消耗,但不会,甚至不会)dwhiled.MoveNext()dEnumddEnumdbc
  2. 我可以以循环以外的方式循环bc(或) ,消耗物品吗?(循环比循环快得多,我担心科学计算问题的性能问题)dforeachwhileforeach
  3. 在类型中究竟消耗BlockingCollection<T>是什么意思?

例如,代码:

IEnumerator<Double> dEnum = d.GetEnumerator();
while (dEnum.MoveNext())
{
    // do the same with dEnum.Current as
    // I would with item in the foreach above...
}

谢谢大家!

4

2 回答 2

4

没有“性能问题” foreachforeach与直接使用循环相比,直接使用枚举器不太可能给您带来任何可衡量的性能改进。

话虽如此,GetConsumingEnumerable()返回一个标准IEnumerable<T>,因此您可以选择任何方式枚举它。IEnumerator<T>直接通过它获取和枚举仍然会以同样的方式工作。

请注意,如果您不想使用GetConsumingEnumerable(),可以直接使用ConcurrentQueue<T>。默认情况下,BlockingCollection<T>包装 a ConcurrentQueue<T>,实际上只是提供了一个更简单的 API ( GetConsumingEnumerable()) 来使 Producer/Consumer 场景更易于编写。直接使用 aConcurrentQueue<T>将更接近于使用BlockingCollection<T>而不使用可枚举。

于 2012-10-05T18:45:36.013 回答
4

如果我得到IEnumerator<Double> dEnum = d.GetEnumerator()from d (例如,用 while 循环遍历 d ) d.MoveNext() 也会消耗列表吗?

绝对地。foreach无论如何,这就是循环要做的所有事情。

我可以以除 foreach 循环之外的方式循环 bc(或 d),消耗这些项目吗?(while 循环比 foreach 循环快得多,我担心科学计算问题的性能问题)

如果您的while循环速度更快,则表明您做错了什么。它们应该完全相同 - 除了foreach循环也会处理迭代器,你应该这样做......

如果您可以发布一个简短但完整的程序来证明这种差异,我们可以更详细地查看它。

另一种方法是使用Take(和类似的方法)。

BlockingCollection 类型中的准确消费是什么意思?

有效地“从集合中删除下一个项目”。

于 2012-10-05T18:46:14.247 回答