2016-08-05 58 views
4

我们都知道的方法如Task.RunParallel.ForEach。 它们中的每一个创建根据单独线程中的选项或线程池中的线程运行的任务。但是,他们的堆栈在哪里?在有些世代堆或有特殊的地方给他们?在C#中分配任务堆栈在哪里?

例如,我可以创建1000个任务,他们的堆栈位于何处?如果我调用GC.Collect(),他们的物理地址是否会在某个时刻移动?

+2

这是相当具体的一个特定的CLR实现,底层操作系统,甚至是CPU架构。例如,Windows特别支持分配(和增长)线程堆栈,与x86/x64内存管理的工作方式一致。 –

+0

确实。在C#语言中很少有任何要求存在任何堆栈(实际上只是堆栈分配 - 在C#语言规范中只有44次出现'stack',其中一半是名为'Stack'的示例类) –

回答

3

堆栈是纯粹非托管的实现细节。处理器需要一个堆栈来完成任何事情,如果没有它,它不能有意义地执行任何代码。它与一个线程紧密相连,而CLR主机是另一个纯粹非托管的细节。

它位于内核中,操作系统内核在创建线程时决定分配它,它是随机的。故意随意给予恶意软件困难时,堆栈是一种将数据转化为恶意代码的有吸引力的方式。不仅位置是随机的,而且堆栈开始的堆栈段内的精确偏移量是随机的。

它创建后永远不会移动,GC不会修补它。它确实需要了解它,可以将对象根存储在堆栈中。因此,可靠的堆栈走是一个很难的.NET要求,也是CLR在程序死于未处理的异常时总能产生良好的堆栈跟踪的基本原因。用完堆栈空间是一个严重的问题,处理器不能继续执行代码。严重到足以说明问题后,程序员的网站:)

2

基于由TaskScheduler执行的代表的任务在TaskScheduler使用的任何堆栈上运行。默认调度程序使用线程池线程。这些(主要)是普通的.NET线程。

特别是,Task.Run创建了这样一个基于默认调度程序的任务。

基于TaskCompletionSource的任务不执行代码,也不需要堆栈。它们是基于一些外部条件完成的,例如IO完成或计时器滴答。

.NET没有对基于堆栈或“绿色线程”的内置支持。你通常不会在真实的代码中找到这样的事情。