2

同時に処理する必要があるファイルのリストがあります。ParallelQuery クラスの ForAll 拡張メソッドを使ってみました。ファイルを順番に処理する必要がないので、ForAll を使用しました。

ここに私のサンプルコードがあります:

List<FileInfo> files = GetFilesToProcess();

files.AsParallel().ForAll(f => { // Process file here });

それはうまく機能しますが、ファイルごとに一意の整数 ID を生成する必要があり、AsParallel.ForAll を ForEach に変更せずにそれを行う方法がわかりません。

インターロックとして必要な場所を読みましたが、まだ問題があります。

ここでアイデアをいただければ幸いです。

ありがとう!

4

2 に答える 2

3

を使用Interlocked.Incrementして ID を生成することも、インデックスを直接使用することもできます。

List<FileInfo> files = GetFilesToProcess();

files.AsParallel().Select((f, i) => new {File=f, ID=i})
     .ForAll(fp => 
           {
              FileInfo file = fp.File;
              int id = fp.ID; // ID is the index in the list

              // Process file here
           });

を使用したい場合はInterlocked.Increment、次のようにします。

List<FileInfo> files = GetFilesToProcess();
int globalId = -1;

files.AsParallel().ForAll(f => 
                         { 
                              // Process file here 
                              int id = Interlocked.Increment(ref globalId);
                              // use ID
                         });

そうは言っても、コレクションで「作業」を行うことが全体の目標である場合は、代わりにこれを Parallel.For または Parallel.ForEach として記述することをお勧めします。これは、副作用を生成するためだけに LINQ スタイルの構文を使用していないため、より明確です。

List<FileInfo> files = GetFilesToProcess();
Parallel.For(0, files.Count, i =>
{
    var file = files[i];
    // Use i and file as needed
});
于 2012-08-28T00:12:26.737 に答える
0

本当に必要な場合は、intを通じて対処することができますInterlocked.Increment

ソースのインデックスを使用することをお勧めします。これは、パーティショナーから既に入手可能な情報であり、提供されるような軽い共有でInterlockedもまだ共有されているためです。

または、それをスキップして、ある種の UUID を使用することもできます。この場合、それはおそらく重すぎて価値がありません (インデックスの取得は素晴らしく軽量です)。「並列タスク間の共有なしでこれを行うことはできますか?」という質問があるので、これについて言及します。後で却下されたとしても、常に考慮する必要があります。

于 2012-08-28T00:14:36.003 に答える