XML要素を返すメソッドがありますが、そのメソッドは終了して値を返すのに時間がかかります。複数のメソッドを同時に複数回実行する#
私が今持っていることは
foreach (var t in s)
{
r.add(method(test));
}
ですが、これが唯一の以前の1が終了した後、次のステートメントを実行します。私はそれを同時に動かすことができますか?
XML要素を返すメソッドがありますが、そのメソッドは終了して値を返すのに時間がかかります。複数のメソッドを同時に複数回実行する#
私が今持っていることは
foreach (var t in s)
{
r.add(method(test));
}
ですが、これが唯一の以前の1が終了した後、次のステートメントを実行します。私はそれを同時に動かすことができますか?
あなたはこのためにタスクを使用することができるはずです。
//first start a task for each element in s, and add the tasks to the tasks collection
var tasks = new List<Task>();
foreach(var t in s)
{
tasks.Add(Task.Factory.StartNew(method(t)));
}
//then wait for all tasks to complete asyncronously
Task.WaitAll(tasks);
//then add the result of all the tasks to r in a treadsafe fashion
foreach(var task in tasks)
{
r.Add(task.Result);
}
EDIT 上記のコードでいくつかの問題があります。動作するバージョンについては、以下のコードを参照してください。ここでは、可読性問題のためにLINQを使用するループを書き直しました(問題の原因となるラムダ式内のt
のクロージャを回避するための最初のループの場合)。
var tasks = s.Select(t => Task<int>.Factory.StartNew(() => method(t))).ToArray();
//then wait for all tasks to complete asyncronously
Task.WaitAll(tasks);
//then add the result of all the tasks to r in a treadsafe fashion
r = tasks.Select(task => task.Result).ToList();
エラー 'System.Threading.Tasks.TaskFactory.StartNew(System.Action)'に最適なオーバーロードされたメソッドに無効な引数があります\t tasks.Add(Task.Factory.StartNew(method(t )))); – ikel
私のコードにいくつかの問題があります。あなたのためにそれを編集する2分を与えてください。 –
ikel - 私の編集を参照してください。コードもちょっと整理されました:) –
Parallel.ForEach
を使用すると、複数のスレッドを使用して並列実行することができます。呼び出されるすべてのコードがスレッドセーフであり、並列に実行できることを確認する必要があります。
Parallel.ForEach(s, t => r.add(method(t));
これは新しいものです。以前はこれを使用したことがありませんでした。私は試してみます。ありがとうございました – ikel
これはほぼOKですが、ここでの問題はrのaddメソッドスレッドセーフではなく、さまざまなスレッドからリストに追加すると**問題が発生します。 –
私はループ内の共有コレクションを更新しています。これは、ループを並列に実行すると、複数のスレッドが同期していないコレクション(がList
などであると仮定します)を同時に更新しようとするため、データの競合が発生し、矛盾した状態が発生するためです。並行して、正しく実行するに
、あなたはロックのステートメント内のコードのセクションをラップする必要があります。
object locker = new object();
Parallel.Foreach (s,
t =>
{
lock(locker) r.add(method(t));
});
しかし、これは実行が実際にシリアルになります、各スレッドがロックを取得する必要があるためと同時に2つのスレッドがそうすることはできません。
各スレッドのローカルリストを作成し、そのリストに部分的な結果を追加し、すべてのスレッドが完了したときに結果をマージする方がよい場合があります。たぶん@ØyvindKnobloch-Bråthenの2番目の解決策は、method(t)
がこの場合のCPUホッグであると仮定すれば、最良の方法です。
修正この質問に対する正しい答えに
へ 変更tasks.Add(Task.Factory.StartNew(method(t);));
は 'r'と' add'と 'method'と' test'スレッドセーフですか? – Yahia