如果 "value type" 变量仍在被另一个线程使用(由 "ref" 传递),那么它如何在离开方法作用域时从堆栈中释放出来?
How is "value type" variable freed from the stack when leaving method scope if it is still in use by another thread (passed by "ref")?
假设我们有一个 method A
声明变量 'int Q',启动另一个 method B
接受变量 Q
作为新线程中的 ref int
参数,并且returns.
考虑到,根据这个答案,.NET 在通过引用传递时将“堆栈中变量 Q 的地址”传递给 method B
- 当控制离开 method A
的范围时,应该运行时间清除了这个方法内部分配的变量栈?这是否意味着如果原始线程继续 运行(并在堆栈上分配其他变量),method B
可能会破坏其中一个变量,因为它引用的“地址”不属于变量 [=15] =] 了?
我肯定理解错了,因为当我 运行 下面的片段时,我没有注意到 manyInts
数组中的任何变化。
public static void Main(string[] args)
{
Outer();
int[] manyInts = new int[100000];
Thread.Sleep(5000);
}
private static void Outer()
{
int crossThreadInt = 10;
try
{
var t = Task.Run(() => AsyncInfiniteMethod(ref crossThreadInt));
t.Wait(2000);
}
catch (Exception)
{
// ignored
}
finally
{
Console.WriteLine(crossThreadInt);
}
}
private static void AsyncInfiniteMethod(ref int number)
{
while (true)
{
Thread.Sleep(100);
number++;
}
}
当您将变量“捕获”到 lambda 委托或匿名方法中时:它会更改位置 - 它不再是堆栈变量。本质上,这个:
int crossThreadInt = 10;
// ...
var t = Task.Run(() => AsyncInfiniteMethod(ref crossThreadInt));
变成:
var captureContext = new SomeCompilerGeneratedClass();
captureContext.crossThreadInt = 10;
// ...
var t = Task.Run(captureContext.SomeCompilerGeneratedMethod);
class SomeCompilerGeneratedClass {
public int crossThreadInt;
public void SomeCompilerGeneratedMethod() {
AsyncInfiniteMethod(ref this.crossThreadInt)
}
// etc
}
所以:问题不存在:整数从来都不是堆栈局部变量;它是 class 上的一个字段。捕获上下文对象(拥有生命周期)保持活动状态,因为它是委托的“目标”实例。
假设我们有一个 method A
声明变量 'int Q',启动另一个 method B
接受变量 Q
作为新线程中的 ref int
参数,并且returns.
考虑到,根据这个答案,.NET 在通过引用传递时将“堆栈中变量 Q 的地址”传递给 method B
- 当控制离开 method A
的范围时,应该运行时间清除了这个方法内部分配的变量栈?这是否意味着如果原始线程继续 运行(并在堆栈上分配其他变量),method B
可能会破坏其中一个变量,因为它引用的“地址”不属于变量 [=15] =] 了?
我肯定理解错了,因为当我 运行 下面的片段时,我没有注意到 manyInts
数组中的任何变化。
public static void Main(string[] args)
{
Outer();
int[] manyInts = new int[100000];
Thread.Sleep(5000);
}
private static void Outer()
{
int crossThreadInt = 10;
try
{
var t = Task.Run(() => AsyncInfiniteMethod(ref crossThreadInt));
t.Wait(2000);
}
catch (Exception)
{
// ignored
}
finally
{
Console.WriteLine(crossThreadInt);
}
}
private static void AsyncInfiniteMethod(ref int number)
{
while (true)
{
Thread.Sleep(100);
number++;
}
}
当您将变量“捕获”到 lambda 委托或匿名方法中时:它会更改位置 - 它不再是堆栈变量。本质上,这个:
int crossThreadInt = 10;
// ...
var t = Task.Run(() => AsyncInfiniteMethod(ref crossThreadInt));
变成:
var captureContext = new SomeCompilerGeneratedClass();
captureContext.crossThreadInt = 10;
// ...
var t = Task.Run(captureContext.SomeCompilerGeneratedMethod);
class SomeCompilerGeneratedClass {
public int crossThreadInt;
public void SomeCompilerGeneratedMethod() {
AsyncInfiniteMethod(ref this.crossThreadInt)
}
// etc
}
所以:问题不存在:整数从来都不是堆栈局部变量;它是 class 上的一个字段。捕获上下文对象(拥有生命周期)保持活动状态,因为它是委托的“目标”实例。