Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 延迟执行时保留范围外堆栈变量_C#_.net_Multithreading_Stack - Fatal编程技术网

C# 延迟执行时保留范围外堆栈变量

C# 延迟执行时保留范围外堆栈变量,c#,.net,multithreading,stack,C#,.net,Multithreading,Stack,我承认这个问题显示了很多关于堆栈和堆栈框架的可能误解。希望我在这里提出一个恰当的问题 在C#中,堆栈帧和局部变量是如何处理如下代码的。这些案例的有趣之处在于,StartTasks中的变量j和StartTasks2中的变量i都被任务使用,这些任务很可能在这些变量不再在作用域中并且在运行它们的堆栈帧之后从堆栈中弹出后运行 此外,在什么情况下,像j这样的局部变量在超出范围后会得到一个全新的内存插槽(如StartTask中发生的情况),并且该局部变量存在于何处(即StartTasks的stackfram

我承认这个问题显示了很多关于堆栈和堆栈框架的可能误解。希望我在这里提出一个恰当的问题

在C#中,堆栈帧和局部变量是如何处理如下代码的。这些案例的有趣之处在于,StartTasks中的变量j和StartTasks2中的变量i都被任务使用,这些任务很可能在这些变量不再在作用域中并且在运行它们的堆栈帧之后从堆栈中弹出后运行

此外,在什么情况下,像j这样的局部变量在超出范围后会得到一个全新的内存插槽(如StartTask中发生的情况),并且该局部变量存在于何处(即StartTasks的stackframe,这意味着无法删除该帧,或其他位置)

void StartTasks(){
int i=0;
而(i<10000){
int j=i;
Task.Run(()=>ExecuteThis(j));//eac
}
}
void StartTasks2(){
int i=0;
而(i<10000){
Task.Run(()=>ExecuteThis(i));//eac
}
}
void BigBoss(){
StartTasks();
StartTasks2();
NowMakeMoreCalls();
}

它们被提升为编译器生成类的一部分

对您提供的内容进行简单的反编译可以给出一些答案:

[CompilerGenerated]
private sealed class <>c__DisplayClass5
{
  public int i;
  public Program <>__this;

  public <>__DisplayClass5()
  {
    base.<>ctor();
  }

  public void <CStartTasks2>b__3()
  {
    this.<>4__this.ExecuteThis(this.i);
  }
}
[编译生成]
专用密封c类显示器Class5
{
公共国际一级;
公共计划;
公共显示类别5()
{
base.ctor();
}
公共空间b_u 3()
{
这个。4_u这个。执行这个(这个。我);
}
}
编译器生成这个类并将调用类的引用传递给它。它还将closed over变量存储为实例字段


所以,要回答这个问题。。它们没有在堆栈上分配。它们形成一个在编译时定义并在运行时实例化的对象。

它们被提升为编译器生成的类的一部分

对您提供的内容进行简单的反编译可以给出一些答案:

[CompilerGenerated]
private sealed class <>c__DisplayClass5
{
  public int i;
  public Program <>__this;

  public <>__DisplayClass5()
  {
    base.<>ctor();
  }

  public void <CStartTasks2>b__3()
  {
    this.<>4__this.ExecuteThis(this.i);
  }
}
[编译生成]
专用密封c类显示器Class5
{
公共国际一级;
公共计划;
公共显示类别5()
{
base.ctor();
}
公共空间b_u 3()
{
这个。4_u这个。执行这个(这个。我);
}
}
编译器生成这个类并将调用类的引用传递给它。它还将closed over变量存储为实例字段

所以,要回答这个问题。。它们没有在堆栈上分配。它们形成一个在编译时定义并在运行时实例化的对象

这个问题显示了很多关于堆栈和堆栈框架的可能误解

你的理解是好的,但你只是没有把所有的事实放在一起来解释。你有90%的成功率

堆栈帧是一个实现细节。不要求将本地端口实现为堆栈插槽。记住,使局部成为局部的不是因为它在堆栈上。它们被称为局部变量,而不是堆栈变量。使局部成为局部的原因是其名称仅在方法内部有意义

这些案例的有趣之处在于,StartTasks中的变量j和StartTasks2中的变量i都被任务使用,这些任务很可能在这些变量不再在作用域中并且在运行它们的堆栈帧之后从堆栈中弹出后运行

首先,您错误地使用了术语“范围”。“范围”是一个编译时概念;局部变量的范围是代码文本的区域,在该区域中,可以通过其名称访问该变量。您正在使用“范围”作为堆栈帧生存期的运行时概念。这不是范围;那是一生

您可以正确地注意到局部变量的生存期长于堆栈帧的生存期。显然,这意味着本地端口不能实现为堆栈插槽。事实并非如此。该局部变量被实现为一个字段。字段是任务引用的对象的字段

在什么情况下,像j这样不断被“重新创建”的局部变量在超出范围后会获得一个全新的内存插槽

当重新使用插槽时,将创建错误的程序!重新使用插槽是一种优化。编译器不会进行创建错误程序的优化

那个局部变量在哪里

如果已知变量的生存期与堆栈帧的生存期相同(或更少),那么它可以继续在堆栈上运行。如果不是这样,那么它就必须放在堆上

这个问题显示了很多关于堆栈和堆栈框架的可能误解

你的理解是好的,但你只是没有把所有的事实放在一起来解释。你有90%的成功率

堆栈帧是一个实现细节。不要求将本地端口实现为堆栈插槽。记住,使局部成为局部的不是因为它在堆栈上。它们被称为局部变量,而不是堆栈变量。使局部成为局部的原因是其名称仅在方法内部有意义

这些案例的有趣之处在于,StartTasks中的变量j和StartTasks2中的变量i都被任务使用,这些任务很可能在这些变量不再在作用域中并且在运行它们的堆栈帧之后从堆栈中弹出后运行

首先,您错误地使用了术语“范围”。“范围”是一个编译时概念;局部变量的范围是代码文本的区域,在该区域中,可以通过其名称访问该变量。您正在使用“范围”作为堆栈帧生存期的运行时概念。这不是范围;那是一生

您可以正确地注意到局部变量的生存期长于堆栈帧的生存期。显然这意味着