使用 Lambda 表达式将数据传递到线程

本文关键字:线程 数据 Lambda 表达式 使用 | 更新日期: 2023-09-27 17:56:11

for (int i = 0; i < 10; i++)
  new Thread (() => Console.Write (i)).Start();

正如预期的那样,上述代码的输出是不确定的,因为 i 变量在整个循环生命周期中引用相同的内存位置。因此,每个线程都会调用 Console.Write 在变量上,该变量的值可能会在运行时更改

然而

for (int i = 0; i < 10; i++)
{
  int temp = i;
  new Thread (() => Console.Write (temp)).Start();
}

也给出了非确定性的输出!我认为变量 temp 是每个循环迭代的局部变量。因此,每个线程捕获了不同的内存位置,并且应该存在 np 问题。

使用 Lambda 表达式将数据传递到线程

您的程序应该有 10 个 lambda,每个 lambda 将 0 到 9 之间的一个数字写入控制台。 但是,不能保证线程将按顺序执行。

也给出了非确定性的输出!

不,不是。我已经检查了十次您的第一个代码(有重复的数字)和第二个代码(没有)。

所以一切都很好。正如它应该的那样。

第二个代码片段应该是确定性的,因为每个线程最终都会写入其temp,并且它们的所有温度都会不同。

但是,它不保证线程将按其创建顺序计划执行。您将看到所有可能的临时工,但不一定按升序排列。

这是OP是正确的证据,他的两段代码都是不正确的。

还有一个有证据的解决方案。

但是需要注意的是,"非确定性"意味着线程接收错误的参数订单将永远无法保证。

下面的代码检查了 OP 代码的第二段,并演示了它是否按预期工作。

我正在存储对(线程标识、参数),然后将其打印出来与线程输出进行比较,以证明对没有改变。我还添加了几百毫秒的随机睡眠,因此 for 索引应该在这些时候明显改变。

        Dictionary<int, int> hash = new Dictionary<int, int>();
        Random r = new Random(DateTime.Now.Millisecond);
        for (int i = 0; i < 10; i++)
        {
            int temp = i;
            var th = new Thread(() =>
            {
                Thread.Sleep(r.Next(9) * 100);
                Console.WriteLine("{0} {1}", 
                    Thread.CurrentThread.GetHashCode(), temp);
            });
            hash.Add(th.GetHashCode(), temp);
            th.Start();
        }
        Thread.Sleep(1000);
        Console.WriteLine();
        foreach (var kvp in hash)
            Console.WriteLine("{0} {1}", kvp.Key, kvp.Value);