c# - 线程接收到错误的参数

标签 c# multithreading .net-3.5

我需要在线程中运行一个带有给定参数的方法。我注意到当我运行它时, 参数错误。对于给出的示例,我有一个包含数字 1-7 的数组 int[] output。对于每个数字,我使用 WriteInt(i) 方法创建一个线程。我希望输出以任何顺序为 1-7,但我始终看到一些数字丢失而其他数字重复。发生了什么事,启动这些线程的正确方法是什么?

(该列表仅用于之后加入线程)

class Program
{
    static void Main(string[] args)
    {
        int[] output = { 1, 2, 3, 4, 5, 6, 7 };

        List<Thread> runningThreads = new List<Thread>();

        foreach (int i in output)
        {
            Thread thread = new Thread(() => WriteInt(i));
            thread.Start();
            runningThreads.Add(thread);
        }
        foreach(Thread t in runningThreads)
        {
            t.Join();
        }
    }

    private static void WriteInt(int i)
    {
        Console.WriteLine(i);
    }
}

示例输出:

3
3
4
5
6
7

最佳答案

由 lambda (() => WriteInt(i)) 创建的闭包正在关闭 variable i,而不是在每次迭代中将值设置为 i。当线程运行时,它使用当时在 i 中设置的值,由于 foreach 循环处理,该值可能已经更改。

你需要一个临时的:

foreach (int i in output)
{
        int temp = i;
        Thread thread = new Thread(() => WriteInt(temp));
        thread.Start();
        runningThreads.Add(thread);
}

有关正在发生的事情的详细信息,请参阅 Eric Lippert 的标题为 Closing over the loop variable considered harmful 的帖子.

此外,在 C# 5 (VS2012) 中,这不再是 foreach 循环的问题。然而,它仍然会在 for 循环中发生。

关于c# - 线程接收到错误的参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12324204/

相关文章:

c# - 如何进行插值

c# - "Cannot use fixed local inside lambda expression"

c# - MVC3如何更新多个项目的库存

java - Kafka 9 KafkaConsumer multiple 似乎没有并行处理消息

ruby - 两个Ruby线程相关的问题

jquery - 错误: Cannot process the message because the content type 'application/json; charset=utf-8 was not the expected type

c# - ObservableCollection - 无法更新 UI

c# - 如何动态加载 XAML 以获取控件信息

c# - 在 WinRT HttpClient 上设置请求内容类型

java - Spring ThreadPoolTask​​Executor 永远不会超出 corePoolSize