4

私は今TPLで働き始めています。このビデオでは、TPLを利用した生産者/消費者モデルの簡単なバージョンを見てきました。

ここに問題があります:

次のコード:

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

IEnumerable<Double>foreachを使用して反復(および自動的に消費)できるanを返します。

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反復処理するため) 、リストも消費されますか?(私の答え:私が何を意味するかを知っているなら、はとリンクされていないので、私はそうは思いません。したがって、それは消費しますが、消費しませんし、さらには)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>ラップしConcurrentQueue<T>、実際には、GetConsumingEnumerable()プロデューサー/コンシューマーシナリオの記述を簡単にするためのより単純なAPI()を提供します。直接使用することは、列挙可能なものを使用せずConcurrentQueue<T>に使用することに近いでしょう。BlockingCollection<T>

于 2012-10-05T18:45:36.013 に答える
4

dからを取得した場合IEnumerator<Double> dEnum = d.GetEnumerator()(たとえば、whileループでdを反復処理する場合)、d.MoveNext()もリストを消費しますか?

絶対。foreachとにかくループが行うのはそれだけです。

foreachループ以外の方法でbc(またはd)をループして、アイテムを消費してもよいですか?(whileサイクルはforeachループよりもはるかに速く、科学計算の問題のパフォーマンスの問題が心配です)

ループが速い場合whileは、何か間違ったことをしていることを示しています。それらはまったく同じである必要があります-foreachループがイテレータも破棄することを除いて、これを行う必要があります...

この不一致を示す短いが完全なプログラムを投稿できる場合は、それをより詳細に調べることができます。

Take別の方法は、 (および同様の方法)を使用することです。

BlockingCollectionタイプで正確に消費するとはどういう意味ですか?

「コレクションから次のアイテムを削除する」を効果的に行います。

于 2012-10-05T18:46:14.247 に答える