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();但之后,而不是等待所有线程完成并继续执行其余代码,它再次进入 new Thread(delegate()... 部分代码,因为变量 i 已经是 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 回答