线程进入循环!!意外行为?

时间:2011-03-01 05:47:31

标签: c# multithreading

我在for循环中创建线程,因为每次迭代都会创建一个线程。在这个线程中,我调用的方法是从路径数组中获取路径。当我逐步运行它调试模式时,使用路径数组中的每个路径调用该方法。但是当我正常运行它时,线程会使用意外路径调用该方法。有一段时间它采用相同的路径2次,有时一直使用相同的路径。

代码有什么问题?我在没有线程的情况下运行代码,它运行得很好,但只是在线程中,问题就出现了。

以下是代码:

 for (int i = 0; i < appConfigDataPath.Length; i++)
 {
      var handle = new EventWaitHandle(false, EventResetMode.ManualReset);
      string serverPath = appConfigDataPath[i];
      string serverName = appConfigDataName[i];

      var threadSplit = new Thread(() =>
                 {
                     ScanProcess(serverPath, serverName);
                     handle.Set();
                 });
      threadSplit.Start();
      waitHandles[i] = handle;
 }

4 个答案:

答案 0 :(得分:3)

您需要定义不同的局部变量,以便在循环的每次迭代中保存路径信息。问题是由于使用带外部变量的Lambda表达式时“闭包”的性质,就像你在这里一样。

如果您在本地循环而不是外部声明serverPathserverName,它应该按预期工作。

答案 1 :(得分:1)

问题是在实际调用ScanProcess之前更改了serverPath。

  1. SERVERPATH = PATH0
  2. startThread0
  3. SERVERPATH = PATH1
  4. thread0:ScanProcess(serverPath,..),serverPath已经是path1
  5. startThread1
  6. thread1:ScanProcess(serverPath,..),serverPath仍为path1
  7. 您需要通过Start函数将值作为副本传递。 试试这个:

    class Data
    {
      public string Path;
      public string Name;
      public EventWaitHandle Handle;
      public Data (string path, string name, EventWaitHandle handle)
      {
         Path = path;
         Name = name;
         Handle = handle;
      }
    }
    
    
    var threadSplit = new Thread((obj) =>
    {
      Data data = obj as Data;
      ScanProcess(data.Path, data.Name);
      data.Handle.Set();
    });
    threadSplit.Start(new Data(serverPath, serverName, handle));
    

答案 2 :(得分:0)

您的 serverPath serverName 位于线程闭包的外部范围内。你应该让他们本地。在循环范围内声明它们将解决此问题。

答案 3 :(得分:0)

我不确定谁在使用waitHandles数组......但是尝试移动作业.....

var threadSplit = new Thread(() =>
{
  ScanProcess(serverPath, serverName);
  handle.Set();
});
waitHandles[i] = handle;  // assign handle before starting thread.
threadSplit.Start();

编辑:正如其他人注意到的那样(bleck ......我错过了它们)serverPath,serverName和handle必须是本地的。