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

时间:2016-08-05 11:32:29

标签: c# multithreading

我们都知道 Task.Run Parallel.ForEach。等方法。 它们中的每一个都创建根据单独线程中的选项或线程池中的线程运行的任务。但是,他们的筹码在哪里?在某些代堆中还是有特殊的地方?

例如,我可以创建1000个任务,他们的堆栈在哪里?如果我调用GC.Collect()?

,他们的物理地址是否会在某个时刻移动

2 个答案:

答案 0 :(得分:3)

堆栈是纯粹的非托管实现细节。处理器需要一个堆栈来完成任何事情,没有它就无法有意义地执行任何代码。它与一个线程紧密相关,这是普通CLR主机上另一个纯粹非托管的细节。

它位于内存中,OS内核决定在创建线程时分配它,它是随机的。故意随机地给恶意软件带来困难,堆栈是将数据转换为恶意代码的有吸引力的方式。不仅位置是随机的,堆栈开始的堆栈段内的确切偏移也是随机的。

创建后它永远不会移动,GC不会修补它。它确实需要了解它,对象根可以存储在堆栈中。因此,可靠的堆栈遍历是一项艰难的.NET要求,也是当程序在未处理的异常上死亡时CLR总能产生良好的堆栈跟踪的基本原因。耗尽堆栈空间是一个严重的问题,处理器无法继续执行代码。严重到足以在该问题之后命名程序员的网站:)

答案 1 :(得分:2)

基于TaskSchedulerTaskScheduler使用的任何堆栈上运行的代理执行的任务。默认调度程序使用线程池线程。这些(通常)是正常的.NET线程。

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

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

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