最大线程堆栈大小 .NET?

20

C#.NET 2.0中一个线程允许的最大堆栈大小是多少?此值是否取决于CLR版本和底层操作系统的位数(32位或64位)?我查看了以下资源:msdn1msdn2

public Thread(
    ThreadStart start,
    int maxStackSize
)
我所能看到的唯一信息是默认大小为1兆字节,在上面的方法中,如果maxStackSize为“0”,则将使用可执行文件头中指定的默认最大堆栈大小。我们可以将标头中的值更改到最大多少?这样做是否明智?谢谢。

《突破Windows极限:进程与线程》(http://blogs.technet.com/b/markrussinovich/archive/2009/07/08/3261309.aspx)可能很有趣。尽管它并没有直接回答这个问题。 - user166390
确实很有趣。谢谢分享。 - Oved
2个回答

36

需要说明的是,这符合雷蒙德·陈所说的“如果你需要知道那么你正在做一些错误的事情”的类别。

64位代码运行的线程默认堆栈大小为4兆字节,32位代码为1兆字节。虽然Thread构造函数可以让您传递一个整数值到int.MaxValue,但在32位机器上永远无法获得那么大的值。堆栈必须适合虚拟内存地址空间中的可用空洞,这通常在进程生命周期早期的~600MB上限。随着您分配内存并破碎地址空间,它会迅速变小。

分配比默认值更多是完全不必要的。当您有一个极度递归的方法导致堆栈溢出时,您可能会考虑这样做。不要这样做,修复算法,因为当任务变得更大时,您仍将使其崩溃。

.NET允许您选择的最小堆栈为250 KB。如果传递的值较小,则会自动四舍五入。这是必要的,因为Jitter和垃圾收集器都需要堆栈空间才能完成工作。同样地,这样做应该是完全不必要的。如果您考虑这样做是因为有很多线程并且使用它们的堆栈消耗了所有虚拟内存,那么您有太多线程。 StackOverflowException是您可能遇到的最严重的运行时异常之一。进程死亡是立即且不可捕获的。

主线程的堆栈大小由EXE头中的选项确定。编译器没有更改它的选项,您必须使用editbin.exe /stack来修补.exe头。


3
我不知道最大值是多少,但MSDN提到了你是否应该这么做:
避免使用此构造函数重载。Thread(ThreadStart)构造函数重载使用的默认堆栈大小是线程的推荐堆栈大小。如果线程有内存问题,最可能的原因是编程错误,例如无限递归。
我从未在C#中遇到过由于除无限递归外的StackOverflow错误。如果真的有递归到那个深度的情况,我会考虑用迭代来替换它。

谢谢Chris。我有一个后台线程,对一组文件执行长时间操作,并出现“内存不足以继续执行程序”的错误。这个问题曾经通过更改maxStackSize值来修复。现在对于不同的文件集,它仍然会出现相同的错误,我正在尝试将值设置为最大可能值并查看结果。同时,我也很好奇max值是多少,因为我找不到它。 - Oved

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