这是我在这个论坛的第一个问题,所以我希望明确:
我在C#中使用Visual Studio 2010 RTM编程
该类的构造函数(转换为线程)始终从最后一个Dictionary Entry中获取值。 我不知道我做错了什么,有人吗?
本准则不起作用:
Dictionary<string, Queue<string>> colas;
public DataDispatcher(Dictionary<string, int> lectoras, ReadEventHandler callback)
{
colas = new Dictionary<string, Queue<string>>();
foreach (KeyValuePair<string, int> pair in lectoras)
{
colas.Add(pair.Key, new Queue<string>>());
Thread hilo = new Thread(
() => new ReadHandler(pair.Value, colas[pair.Key], callback));
hilo.Name = "Hilo-" + hilo.ManagedThreadId.ToString();
hilo.Start();
}
}
相反,此代码完美无缺:
Dictionary<string, Queue<string>> colas;
public DataDispatcher(Dictionary<string, int> lectoras, ReadEventHandler callback)
{
colas = new Dictionary<string, Queue<string>>();
foreach (KeyValuePair<string, int> pair in lectoras)
{
Queue<string> qs = new Queue<string>();
colas.Add(pair.Key, qs);
int jaula = pair.Value;
Thread hilo = new Thread(
() => new ReadHandler(jaula, qs, callback));
hilo.Name = "Hilo-" + hilo.ManagedThreadId.ToString();
hilo.Start();
}
}
答案 0 :(得分:2)
这是一个非常常见的错误,称为“捕获循环变量”或“关闭变量”。
foreach (KeyValuePair<string, int> pair in lectoras)
{
colas.Add(pair.Key, new Queue<string>>()); // here 'pair' is OK
var copy = pair; // this is the fix, make a new 'copy' for each thread
Thread hilo = new Thread(
() => new ReadHandler(copy.Value, colas[copy.Key], callback));
}
您使用相同的变量pair
开始了许多线程。此“捕获”变量的行为类似于引用传递参数。当线程开始执行时foreach()
完成,它们都使用最后一个元素。
另外,您可能不应该使用裸线程。使用TPL中的ThreadPool或Task对象。
答案 1 :(得分:1)
是。你是被称为“捕获变量”的受害者。这里捕获的是pair
。请参阅此文章:http://blog.sluu.org/captured-variable/
修改:我还注意到OP的第一个代码段中出现语法错误:colas = new Dictionary<string, Queue<string>>();
此行中有一个更大的符号。