【问题标题】:C# Multiple Threads for work then wait until all finishedC# 多线程工作然后等到全部完成
【发布时间】:2012-10-08 01:08:50
【问题描述】:

我正在开发小型 SSHClient。我有一个连接到不同计算机的客户端列表。我有一个要在这些计算机上运行的脚本。我想在不同的线程中并行运行它。 我在这里受到启发: Stackoverflow - threads

这是我的一段代码:

 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 循环已经完成,它怎么可能创建另一个线程。又该如何避免呢?

谢谢

【问题讨论】:

  • 似乎问题就在clients.Count附近。贴出更多相关代码
  • 为什么不直接使用 Thread.Join?
  • ... 或者您的 clients 数组在循环运行期间被更改(来自其他线程?)?
  • TPL(任务并行库)不会使这几乎成为一个单行吗?
  • 变量i 被捕获。典型的闭包问题。

标签: c# multithreading


【解决方案1】:

在我看来,这很混乱。我建议改用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

【讨论】:

    【解决方案2】:

    您可以使用并行 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 查询并获取每个结果以对它们求和

    【讨论】:

    • 唯一的问题是我们不知道cmd.Result 是什么。它可能是字符串,在这种情况下+= 是连接,所以你不能使用Sum()
    • 我们总是可以使用 Aggregate 来解决这个问题。 msdn.microsoft.com/en-us/library/…
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-07
    • 2013-01-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多