为什么c#不保留匿名委托调用的上下文?

Mo *_*our 5 .net c# multithreading delegates c#-4.0

我有以下方法:

static Random rr = new Random();
static void DoAction(Action a)
{
    ThreadPool.QueueUserWorkItem(par =>
    {
        Thread.Sleep(rr.Next(200));
        a.Invoke();
    });
}
Run Code Online (Sandbox Code Playgroud)

现在我在这样的for循环中调用它:

for (int i = 0; i < 10; i++)
{
    var x = i;

    DoAction(() =>
    {
        Console.WriteLine(i); // scenario 1
        //Console.WriteLine(x); // scenario 2
    });
}
Run Code Online (Sandbox Code Playgroud)

在方案1中,输出为:10 10 10 10 ... 10
在方案2中,输出为:( 2 6 5 8 4 ... 0随机排列0到9)

你怎么解释这个?c#不应该i为匿名委托调用保留变量(这里)吗?

Jar*_*Par 10

这里的问题是有一个i变量和十个实例/副本x.每个lambda都获得对单个变量i和其中一个实例的引用x.每个 x只写一次,因此每个lambda看到一个值写入它引用的值.

i写入变量直到达到10.在循环完成之前,所有lambda都没有运行,因此它们都看到最终值为i10

如果你按如下方式重写它,我觉得这个例子有点清楚

int i = 0;  // Single i for every iteration of the loop
while (i < 10) { 
  int x = i;  // New x for every iteration of the loop 
  DoAction(() => {
    Console.WriteLine(i);
    Console.WriteLine(x);
  });
  i++;
};
Run Code Online (Sandbox Code Playgroud)