2011-03-01 84 views
1

我在循环中创建线程,按照迭代创建一个线程。在这个线程中,我调用了一个从路径数组中取得路径的方法。当我一步一步地运行调试模式时,线程会从路径数组中调用每个路径的方法。但是当我正常运行它时,线程会调用具有意外路径的方法。有些时候,它会使用相同的路径2次,有时使用相同的路径。线程for循环!意外的行为?

代码有什么问题?我运行的代码没有线程它运行完美,但只有在线程的问题。

下面是代码:

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; 
} 
+0

你应该设置IsBackgroundThread属性为true。更重要的是,使用ThreadPool中的线程或使用并行任务来获得更好的性能。 – 2011-03-01 05:53:06

+0

这只是问题所在。我急于使用线程池或并行进行....我必须使用正常线程执行 – PawanS 2011-03-01 05:57:20

+0

ScanProcess执行什么操作?它使用数组吗? – 2011-03-01 06:08:38

回答

1

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

  1. SERVERPATH = PATH0
  2. startThread0
  3. SERVERPATH = PATH1
  4. thread0:ScanProcess(SERVERPATH,..),SERVERPATH已经PATH1
  5. startThread1
  6. 线程1:ScanProcess(SERVERPATH ,. 。),serverPath仍然是路径1

您需要传递thr中的值尽可能将启动功能作为副本。 试试这个:

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)); 
3

您需要定义不同,局部变量来保存在每次循环的路径信息。这个问题是由于在使用带有外部变量的Lambda表达式时的'闭包'的性质,因为您在这里。

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

+1

+1,但OP编辑他的问题以显示在本地声明的变量。但最初的代码可能是他正在运行的。 – Josh 2011-03-01 06:14:51

+0

@乔什爱因斯坦 - 看起来像我*可能*他编辑的代码来尝试,并没有奏效。至少,这就是我要做的,要礼貌!我认为我们需要看到这个impl。该方法虽然。 – 2011-03-01 10:22:28

0

您的serverPathserverName位于线程关闭的外部范围内。你应该让他们当地。在循环范围内声明它们可以解决这个问题。

+0

不,这不能解决问题 – PawanS 2011-03-01 06:04:01

+0

@GAPS:奇怪。你有没有试图把'threadSplit.Start();'放在循环结尾?如果它不能工作,你应该向我们展示'ScanProcess'的实现。 – 2011-03-01 06:16:27

0

我不知道谁在使用waitHandles阵列...但尝试移动分配.....

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

编辑:正如其他人注意到(布莱克......我想念他们) serverPath,serverName和句柄必须是本地的。