我在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;
}
答案 0 :(得分:3)
您需要定义不同的局部变量,以便在循环的每次迭代中保存路径信息。问题是由于使用带外部变量的Lambda表达式时“闭包”的性质,就像你在这里一样。
如果您在本地循环而不是外部声明serverPath
和serverName
,它应该按预期工作。
答案 1 :(得分:1)
问题是在实际调用ScanProcess之前更改了serverPath。
您需要通过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必须是本地的。