为什么Thread.Start可能会抛出OutOfMemoryException?

15

这个问题与我之前的问题“线程开销”有关。

既然Thread.Start没有为线程声明内存来运行,那么它为什么会抛出OutOfMemoryException


你在线程里面做什么? - musefan
1
无论线程正在做什么,它们自己会抛出OutOfMemoryExceptions,不会回流到thread.start。 - BrainSlugs83
3个回答

24

这是启动CLR中托管线程的部分源代码:

CExecutionEngine::SetupTLSForThread(pThread);
if (!pThread->InitThread(fInternal) ||
    !pThread->PrepareApartmentAndContext())
    ThrowOutOfMemory();
if (UnsafeTlsSetValue(gThreadTLSIndex, (VOID*)this) == 0)
{
    ThrowOutOfMemory();
}
if (UnsafeTlsSetValue(GetAppDomainTLSIndex(), (VOID*)m_pDomain) == 0)
{
    ThrowOutOfMemory();
}

看起来它在许多情况下可能会引发内存不足;如果线程无法初始化,如果无法准备单元或上下文环境,或者如果无法分配线程本地存储,则会抛出“内存不足”的异常。

在我看来,这是一个不好的想法;我更喜欢将“内存不足”保留给“我尝试分配一个新的虚拟内存块,并且我找不到所需大小的块”的情况。对于诸如没有可用的TLS插槽或线程初始化失败等情况,抛出内存不足异常只会令人困惑。


4
虽然线程的堆栈仅在线程实际启动时才被声明,但注册执行线程仍需要一些内存,因此可能会导致OutOfMemoryException。

0

我认为你误解了一些东西。线程需要内存才能启动。每个线程都有它自己的 堆栈堆栈指针等,必须为这些内存留出空间。如果你没有足够的内存,就会抛出一个 异常


你可能想阅读链接问题的答案。它指出堆栈仅在线程实际启动时才被占用。Thread.Start不会这样做,它只是安排线程启动。 - Daniel Hilgarth
可能,但您确切知道那里发生了什么吗? - bash.d

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