2

私は小さなSSHClientに取り組んでいます。さまざまなコンピューターに接続されているクライアントのリストがあります。それらのコンピューターで実行したいスクリプトがあります。異なるスレッドで並行して実行したいと思います。私はここでインスピレーションを得ました: Stackoverflow-スレッド

これが私のコードです:

 int toProcess, count = 0;
        ManualResetEvent resetEvent = new ManualResetEvent(false);
        toProcess = count = clients.Count;
        for (int i = 0; i < count; i++)
        {
                new Thread(delegate()
                {
                    var cmd = clients[i].RunCommand("./script.sh");
                    res += cmd.Result;
                    if (Interlocked.Decrement(ref toProcess) == 0)
                        resetEvent.Set();
                }).Start();
        }
        resetEvent.WaitOne();

        //do something

私には、このコードは問題ないように見えます。しかし、場合によっては(実際にはほとんどの場合)、プログラムがforループから正しく外れたresetEvent.WaitOne();後、正しく行に到達しますが、その後、すべてのスレッドが終了して残りのコードを続行するのを待つのではなく、再び新しいThread(delegate()...コードの一部に移動し、変数iがすでに2であるため(クライアントのリストに2つのクライアントがある場合)、エラーが発生します。

インデックスが範囲外でした。負ではなく、コレクションのサイズよりも小さい必要があります。

forループが終了しても、別のスレッドが作成される可能性があるのか​​どうかを尋ねたいと思いました。そしてそれを回避する方法は?

ありがとうございました

4

2 に答える 2

3

私の意見では、これは厄介です。代わりに使用することをお勧めしParallel.Forます:

 int toProcess, count = 0;
 toProcess = count = clients.Count;
 object locker = new object();
 Parallel.For(0, count, i =>
 {
     var cmd = clients[i].RunCommand("./script.sh");
     lock(locker) res += cmd.Result;
 });

このリンクを参照してください:Parallel.For

于 2012-10-07T16:43:48.693 に答える
0

並列linqクエリを使用して、Sumメソッドを介してその結果を集計できます。

var totalResult = (from i in Enumerable.Range(0, client.Count).AsParallel()
                   let cmd = clients[i].RunCommand("./script.sh")
                   select cmd.Result).Sum();

AsParallelメソッドを使用して、できるだけ多くのスレッドを作成し、Sumメソッドを使用して、linqクエリを実行し、各結果をフェッチして合計します。

于 2012-10-07T17:08:50.283 に答える