.net 4.0 是唯一一种使用区块集合的方法<;T>;在C#中?
我现在开始和TPL合作。我已经看到了一个简单版本的生产者/消费者模型,它在中使用了第三方物流 问题是: 以下代码:.net 4.0 是唯一一种使用区块集合的方法<;T>;在C#中?,.net-4.0,task-parallel-library,blockingcollection,.net 4.0,Task Parallel Library,Blockingcollection,我现在开始和TPL合作。我已经看到了一个简单版本的生产者/消费者模型,它在中使用了第三方物流 问题是: 以下代码: BlockingCollection<Double> bc = new BlockingCollection<Double>(100); IEnumerable<Double> d = bc.GetConsumingEnumerable(); 我的问题是: 如果我从d中获得IEnumerator dEnum=d.GetEnumerator()(
BlockingCollection<Double> bc = new BlockingCollection<Double>(100);
IEnumerable<Double> d = bc.GetConsumingEnumerable();
我的问题是:
d
中获得IEnumerator dEnum=d.GetEnumerator()
(例如,在while
循环中迭代d
),那么d.MoveNext()
是否也会使用该列表?(我的回答是:我不这么认为,因为dEnum
与d
没有联系,如果你知道我的意思的话。因此它会消耗dEnum
,但不会消耗d
,甚至也不会消耗bc
)foreach
循环以外的方式循环使用bc
(或d
)项目吗?(while循环比foreach循环快得多,我担心科学计算问题的性能问题)BlockingCollection
类型中,消费到底意味着什么IEnumerator<Double> dEnum = d.GetEnumerator();
while (dEnum.MoveNext())
{
// do the same with dEnum.Current as
// I would with item in the foreach above...
}
IEnumerator dEnum=d.GetEnumerator();
while(dEnum.MoveNext())
{
//对dEnum做同样的处理。电流为
//我想用上面的表格中的项目。。。
}
提前谢谢大家 foreach不存在“性能问题”。与直接使用foreach
循环相比,直接使用枚举器不太可能给您带来任何可测量的性能改进
也就是说,返回一个标准的IEnumerable
,因此您可以选择任何方式枚举它。获取IEnumerator
并直接对其进行枚举仍将以相同的方式工作
请注意,如果您不想使用
GetConsumingEnumerable()
,可以直接使用。默认情况下,BlockingCollection
包装了一个ConcurrentQueue
,实际上只是提供了一个更简单的API(getconsumineGenumerable()
)来简化生产者/消费者场景的编写。直接使用ConcurrentQueue
将更接近于在不使用可枚举项的情况下使用BlockingCollection
如果我从d获取IEnumerator dEnum=d.GetEnumerator()
(例如,用while循环迭代d),d.MoveNext()是否也会使用该列表
当然。这就是foreach
循环所能做的一切
我可以用foreach循环以外的方式循环bc(或d)来使用这些项目吗?(while循环比foreach循环快得多,我担心科学计算问题的性能问题)
如果while
循环速度更快,则表明您做错了什么。它们应该完全相同-除了foreach
循环也会处理迭代器,您应该这样做
如果您可以发布一个简短但完整的程序来演示这种差异,我们可以更详细地了解它
另一种方法是使用(和类似的方法)
在BlockingCollection类型中,消费到底意味着什么
有效地“从集合中删除下一项”。为什么您认为
foreach
会有性能问题?好吧,我已经做了一些真正的虚拟测试(比如遍历包含数百万个元素的数组,并对数组的每个项执行完全相同的条件检查)并测量了在期间、在期间以及在每个期间完成任务所花费的时间。。。在中,while
的速度要快得多…当我回应@Reed的评论时,我做了一些虚拟测试,while
似乎更快。。。至少在处理非视差问题时…@Girardi:你的评论谈到了对数组的迭代。您是否确实迭代了阻止集合
?而且,这样的基准测试很容易出错。这就是为什么我要求一个简短但完整的程序来演示这个问题——基于错误的假设,走完全不同的路线是没有意义的。好吧,因为我对第三方物流一无所知,所以我没有测试BlockingCollection
。因此,我可能毕竟做出了错误的假设…@Girardi:一如既往-首先让代码以简单的方式工作,然后测量性能。@Girardi:它将代码从阻塞集合中删除。这就是为什么它是一个“消费枚举”。在getConsuminegumerable
的文档中:“一个从集合中删除并返回项目的IEnumerable。”当我回复@Reed的评论时,我做了一些虚拟测试,而似乎更快。。。至少在处理非视差问题时…@Girardi通常情况下,语言结构本身的性能差异与正在执行的任何计算相比都是微不足道的。如果您使用的是BlockingCollection
,这一点尤其正确-while/for/foreach的差异与将项目放入和移出集合的开销相比将是微小的。因此,我不会在您的优化中重点关注这一点—关注最干净的算法是什么,这样您就可以发现并解决“真正”的性能问题(在使用这些项的代码中)BlockingCollection
不仅仅是ConcurrentQueue
(或其他并发集合)的简单API。它的要点是,它的方法会阻塞,直到可以执行操作为止。例如,如果您想使用ConcurrentQueue
实现BlockingCollection.Take()
的替代方案,则需要手动使用一些同步构造(如ManualResetEvent
)。@svick Yes-抱歉,我意识到我的措辞也不太清楚。BC向ConcurrentQueue添加“阻塞”部分,包括.Take和.GetConsumingEnumerable。如果你想要这个
IEnumerator<Double> dEnum = d.GetEnumerator();
while (dEnum.MoveNext())
{
// do the same with dEnum.Current as
// I would with item in the foreach above...
}