c#多线程应用程序

时间:2012-12-20 13:41:01

标签: c# multithreading

我对c#和多线程有些新意,所以我可能在这里犯了一个愚蠢的错误,但我似乎无法解决这个问题。我有一个应用程序,它根据我的网络上发现的机器数量创建一个线程数组,然后为每台机器创建一个执行我创建的函数的线程。退出for循环后,我创建另一个运行另一个函数的线程。我的函数完全正常,并且没有问题,问题出于某种原因退出for循环并继续创建下一个线程,我的应用程序跳回到for循环,索引现在超出范围并导致被抛出的异常。我希望我能清楚地解释这一点,我很困惑为什么会发生这种情况,因为我不知道为什么当完成for循环时它会执行一行代码并跳回来。无论如何这里是我的代码任何帮助将不胜感激

        smThread = new Thread[networkedComputers.Count];

        for (UInt16 i = 0; i < networkedComputers.Count; i++)
        {
            smThread[i] = new Thread(delegate() { sm.RunServerMonitorPerMachine(networkedComputers[i].ToString()); });
            smThread[i].Start();
        }

        dailyThread = new Thread(dailyEvents);
        dailyThread.Start();

2 个答案:

答案 0 :(得分:6)

我认为你的问题就在这里:

networkedComputers[i].ToString()
                   ^

执行此操作时,您可能希望将i的值传递给线程,但实际上,您将引用传递给i。循环时此引用会更新,因此当线程实际执行时,它很可能不是您期望的值。 (Google关键字:捕获变量)

解决方案是在将值传递给线程之前复制该值。此副本不会更新。

for (int i = 0; i < networkedComputers.Count; i++)
{
    int tmp = i;
    smThread[i] = new Thread(delegate() { sm.RunServerMonitorPerMachine(networkedComputers[tmp].ToString()); });
    smThread[i].Start();
}

答案 1 :(得分:1)

捕获的循环变量的问题很可能是您的问题,正如Kendall Frey指出的那样。但是,正如你帖子中的其他一些评论者所说,这可能是查看C#的任务并行库的好例子,它可以为你处理很多这些事情。您的代码看起来像这样:

for (UInt16 i = 0; i < networkedComputers.Count; i++) {
    int count = i;
    Task.Factory.StartNew(() => sm.RunServerMonitorPerMachine(networkedComputers[count].ToString());
}

Task.Factory.StartNew(() => dailyEvents());

这样做的好处是,您不必担心管理线程池,因为一旦线程可用于执行任务,任务就会排队并获取。另一件需要考虑的事情是,在for循环中的所有任务完成之前,执行dailyEvents任务的工作并不多。这是你当前的解决方案中没有实现的东西(但是从我认为你想要的东西的外观来看);