.NET中的multithreading和闭包

如果我有这个:

public string DoSomething(string arg) { string someVar = arg; DoStuffThatMightTakeAWhile(); return SomeControl.Invoke(new Func(() => someVar)); } 

并且这个方法可以从多个线程同时调用,并且一个线程停留在DoStuffThatMightTakeAWhile ,然后第二个线程调用具有不同arg DoSomething ,这将改变所有线程的someVar的值,因此, DoSomething返回第二个版本的两个调用中的someArg ,或者每个线程someVar存在一个someVar吗?

编辑我认为我的Action应该是一个Func所以编辑它。

这里的答案中存在许多混淆,主要是基于“在线程堆栈上”分配局部变量的不实之处。 这既虚假又无关紧要。

这是错误的,因为局部变量可能分配在某个临时池或长期存储池中; 即使它是在临时池上分配的,也不需要堆栈内存; 它可能是一个注册。 这是无关紧要的,因为谁关心分配存储的池?

相关的事实是每个方法激活分配一个顶级局部变量。 更一般地,块中的局部变量按输入的块分配一次; 例如,每当循环遍历时,就会在循环体中声明一个局部变量。

那么,让我们考虑你的问题:

可以从多个线程同时调用此方法。 如果一个线程停留在DoStuffThatMightTakeAWhile,然后第二个线程调用具有不同arg的DoSomething,这会改变所有线程的someVar的值吗?

不。 每次激活 DoSomething 都会有一个新的“someVar”。

每个线程都会存在一个someVar吗?

每次激活都会存在一个“someVar”。 如果一个线程只执行一次激活,那么每个线程将只有一个someVar; 如果一个线程进行了一百万次激活,那么将有一百万次激活。

也就是说,Jon Hanna的回答也是正确的:如果你创建了一个既读取又写入局部变量的委托 ,又将该委托交给多个线程,那么委托的所有激活共享相同的局部变量。 没有为您创造神奇的线程安全; 如果你想这样做,那么你有责任确保线程安全。

局部变量存储在当前线程的堆栈中,因此每个线程都有自己的堆栈,并且每个线程都拥有someVar变量。

因为每个线程中的值都不同

 new Action(() => someVar)); 

将捕获它自己的someVar值。

编辑

埃里克指出,我完全错了。 请参阅他的答案以获得正确的解

如上所述,每个线程击中DoSomething someVar在其堆栈上创建一个单独的someVar ,因此没有线程对另一个的someVar有任何影响。

值得注意的是,如果在闭包中捕获了本地并且在该作用域中启动了multithreading,则这确实会导致不同的线程影响彼此看到的值,即使在值类型的情况下(我们通常认为不是另一种方法可以影响的东西 – 这样闭包不像类方法:

 public static void Main(string[] args) { int x = 0; new Thread(() => {while(x != 100){Console.WriteLine(x);}}).Start(); for(int i = 0; i != 100; ++i) { x = i; Thread.Sleep(10); } x = 100; Console.ReadLine(); } 

certificate了这一点。