【问题标题】:Confused about multi-threading in a loop for C# [duplicate]对 C# 循环中的多线程感到困惑 [重复]
【发布时间】: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]

【问题讨论】:

    标签: c# multithreading


    【解决方案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 方法来防止这种行为。

    【讨论】:

    • 谢谢。我也想到了,但我就是不明白为什么。
    猜你喜欢
    • 2017-05-03
    • 2018-10-03
    • 2016-07-13
    • 1970-01-01
    • 1970-01-01
    • 2023-01-13
    • 2020-08-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多