.net 4.0 是唯一一种使用区块集合的方法<;T>;在C#中?

.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()(

我现在开始和TPL合作。我已经看到了一个简单版本的生产者/消费者模型,它在中使用了第三方物流

问题是:

以下代码:

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...
    }