C#中任务堆栈分配在哪里?

5
我们都知道像 Task.Run 或者 Parallel.ForEach 这样的方法。 它们每个都会创建任务,在单独的线程或线程池中运行。但是,它们的堆栈在哪里呢?它们是在某个代的堆中还是有专门的地方?
例如,我可以创建1000个任务,它们的堆栈在哪里?如果我调用 GC.Collect(),它们的物理地址是否会移动?

2
这是针对特定的CLR实现、底层操作系统甚至CPU架构而言的。例如,Windows具有特定的支持来分配(和增长)线程堆栈,与x86/x64内存管理的工作方式相一致。 - Ondrej Tucny
的确。在C#语言中,几乎没有任何需要存在堆栈的要求(实际上只有堆栈分配 - 在C#语言规范中只出现了44次stack,其中一半是名为Stack的示例类)。 - Damien_The_Unbeliever
2个回答

5
栈是纯粹的非托管实现细节。处理器需要栈来完成任何操作,否则它无法有意义地执行任何代码。它与线程强烈关联,在正常CLR主机上是另一个纯粹的非托管细节。
它位于内存中,当创建线程时,操作系统内核决定分配它的位置,这是随机的。故意随机以使恶意软件难以攻击,栈是将数据转换为恶意代码的吸引方式。不仅位置是随机的,而且栈段内确切偏移量也是随机的。
在创建后它永远不会移动,GC不会对其进行更改。它确实需要知道它,对象根可以存储在栈上。因此,可靠的栈遍历是.NET的一个重要需求,也是CLR能够在未处理的异常导致程序死亡时始终生成良好的堆栈跟踪的基本原因。栈空间不足是一个严重的问题,处理器无法继续执行代码。严重到足以用该问题命名程序员的网站 :)

2
基于委托的任务由TaskScheduler执行,它们在TaskScheduler使用的堆栈上运行。默认调度程序使用线程池线程,这些线程(大多数情况下)是普通的.NET线程。
特别地,Task.Run创建这样一个基于默认调度程序的任务。
基于TaskCompletionSource的任务不执行代码,也不需要堆栈。它们是基于某些外部条件完成的,例如IO完成或计时器滴答声。
.NET没有内置支持堆栈或“绿色线程”的功能。你通常在真实代码中找不到这样的东西。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接