0

私は自分の懸念を説明するためにいくつかのコードを書きました:

static void Main(string[] args)
{
    IEnumerable<decimal> marks = GetClassMarks();
    IEnumerable<Person> students = GetStudents();

    students.AsParallel().ForAll(p => GenerateClassReport(p, marks));

    Console.ReadKey();
}

GetClassMarksは、奇妙なデータソースからのyieldreturnを使用します。GenerateClassReportは基本的にmarks.Sum()/ marks.Count()を実行して、クラスの平均を取得するとします。

私が理解していることから、students.AsParallel()。ForAllは並列foreachです。

私の心配は、GetClassMarksメソッド内で何が起こるかということです。

  • 一度だけ列挙されるのでしょうか、それとも何度も列挙されるのでしょうか。
  • 列挙はどのような順序で行われますか?
  • マークに対して.ToList()を実行して、1回だけヒットするようにする必要がありますか?
4

3 に答える 3

4

一度だけ列挙されるのでしょうか、それとも何度も列挙されるのでしょうか。

が1回GenerateClassReport()列挙されると仮定すると、の各要素に対して1回列挙されます。marksmarksstudents

列挙はどのような順序で行われますか?

各スレッドはデフォルトの順序でコレクションを列挙しますが、複数のスレッドが同時に列挙します。同時列挙の順序は、通常、予測できません。また、スレッドの数は制限されており、可変であるため、すべての列挙が同時に発生するわけではないことに注意してください。

マークに対して.ToList()を実行して、1回だけヒットするようにする必要がありますか?

がイテレータの場合GetClassMarks()(つまり、yield構造を使用する場合)、その実行は延期され、marks列挙されるたびに1回(つまり、の各要素に対して1回)呼び出されstudentsます。を使用する場合、IEnumerable<decimal> marks = GetClassMarks().ToList()またはGetClassMarks()内部で具象リストまたは配列を返す場合は、GetClassMarks()すぐに実行され、結果は再度呼び出されることなく、各並列スレッドに格納および列挙されますGetClassMarks()

于 2010-07-05T14:47:42.757 に答える
1
  1. GetClassMarksがイテレータの場合、つまり内部で使用している場合、それは事実上、呼び出しなどyieldを呼び出すたびに再実行されるクエリです。marks.Sum()marks.Count()

  2. 並列クエリで実行の順序を予測することはほとんど不可能です。

  3. はい。以下は、それGetClassMarksが一度だけ実行されることを保証します。以降のetcの呼び出しではmarks.Sum()、クエリmarks.Count()を再実行するのではなく、具象リストが使用されGetClassMarksます。

    List<decimal> marks = GetClassMarks().ToList();
    

ポイント13は、を使用しているかどうかに関係なく適用されることに注意してくださいAsParallel。どちらのGetClassMarks場合も、クエリはまったく同じ回数実行されます(並列の側面を除いて、コードの残りの部分が同じであると想定しています)。

于 2010-07-02T12:38:43.443 に答える
0

一度だけ列挙されるのでしょうか、それとも何度も列挙されるのでしょうか。

一度だけ。

列挙はどのような順序で行われますか?

イテレータ(を使用する関数yield)が順序を決定します。

マークに対して.ToList()を実行して、1回だけヒットするようにする必要がありますか?

いいえ。

AsParallel入力を1回だけ繰り返し、入力をブロックに分割して、ワーカースレッドにディスパッチします。

于 2010-07-02T12:17:39.857 に答える