对 C# 循环中的多线程感到困惑 [重复]
Posted
技术标签:
【中文标题】对 C# 循环中的多线程感到困惑 [重复]【英文标题】:Confused about multi-threading in a loop for C# [duplicate] 【发布时间】:2012-03-08 07:11:31 【问题描述】:可能重复:C# Captured Variable In Loop
我对多线程编程很陌生。 当我运行下面的代码时,只有最后一个孩子被执行。 有人能告诉我发生了什么吗? 非常感谢。
private void Process()
Dictionary<int, int> dataDict = new Dictionary<int, int>();
dataDict.Add(1, 2000);
dataDict.Add(2, 1000);
dataDict.Add(3, 4000);
dataDict.Add(4, 3000);
foreach (KeyValuePair<int, int> kvp in dataDict)
Console.WriteLine("Ready for [" + kvp.Key.ToString() + "]");
Task.Factory.StartNew(() => DoSomething(kvp.Value, kvp.Key));
private static void DoSomething(int waitTime, int childID)
Console.WriteLine("Start task [" + childID.ToString() + "]");
Thread.Sleep(waitTime);
Console.WriteLine("End task [" + childID.ToString() + "]");
输出
Ready for [1]
Ready for [2]
Ready for [3]
Ready for [4]
Start task [4]
Start task [4]
Start task [4]
Start task [4]
End task [4]
End task [4]
End task [4]
End task [4]
【问题讨论】:
【参考方案1】:通过在 lambda 中使用循环变量,所有变量都有效地引用同一个变量,这是它们运行时字典的最后一项。
在将循环变量传递给 lambda 之前,您需要将循环变量分配给循环本地的另一个变量。这样做:
foreach (KeyValuePair<int, int> kvp in dataDict)
var pair = kvp;
Console.WriteLine("Ready for [" + pair.Key.ToString() + "]");
Task.Factory.StartNew(() => DoSomething(pair.Value, pair.Key));
编辑:这个小陷阱似乎在 C#5 中得到修复。这就是为什么它可能对其他人有用;)请参阅 labroo 的评论
【讨论】:
人们应该真正解释他们为什么投反对票,这对我来说似乎是一个合理的解释 为什么要投反对票,我不知道这是否是解决方案,但这是一个有效的改变......blogs.msdn.com/b/ericlippert/archive/2009/11/12/… 我也想知道。看不出我的回答有什么问题。 顺便说一句,Botz3000 的回答暗示的是所有线程都在运行......但是,当它们有机会运行时,kvp == 4 我也想过,但我就是不明白为什么。【参考方案2】:您可以通过将 kvp 分配给 for 循环中的局部变量并将变量字段 Key 和 Value 传递给 DoSomething 方法来防止这种行为。
【讨论】:
谢谢。我也想到了,但我就是不明白为什么。以上是关于对 C# 循环中的多线程感到困惑 [重复]的主要内容,如果未能解决你的问题,请参考以下文章