为什么E_OUTOFMEMORY后面跟着"no more threads can be created"?



我有有效的代码(所有这些try-catch看起来都很疯狂,但我真的需要它们来说明问题):

Exception doStuffException = null;
try {
   someComObject.DoStuff();
} catch( Exception e ) {
   doStuffException = e;
   throw;
} finally {
   try {
      someComObject.Cleanup();
   } catch( Exception e ) {
      var processes = Process.GetProcesses();
      foreach( var p in processes ) {
         //log p.Threads.Count and p.ProcessName
      }
      throw;
   }
}

COM对象驻留在进程外服务器进程中。客户端和COM服务器都在Azure web角色中运行,我不知道在Azure之外是否会再次发生同样的行为。

大多数时候,它只是起作用——DoStuff()运行正常,然后Cleanup()运行正常。有时在一些特定的数据集上,DoStuff()产生System.OutOfMemoryException,然后Cleanup()运行并产生System.Runtime.InteropServices.COMException,错误代码0x800700A4对应于winerror.h中定义的ERROR_MAX_THRDS_REACHED,并具有文本"系统中无法再创建线程"。枚举所有进程的代码运行,没有任何进程有任何不合理的线程数,托管COM服务器的进程的线程数等于3(是的,只有三个)。

一旦ERROR_MAX_THRDS_REACHED发生,对该COM服务器的所有调用也会产生ERROR_MAX_THRDS_REACHED,直到COM服务器重新启动。

当线程没有明显泄漏时,是什么原因导致ERROR_MAX_THRDS_REACHED

经过多次观察,很明显,在大多数情况下,问题都会重现,COM服务器进程几乎会消耗所有内存(COM服务器是一个32位进程,因此它消耗的内存不能超过2GB)。

这种情况可能是由于内存碎片或内存泄漏造成的——如果不进行进一步分析,很难说。这反过来可能导致没有足够的内存来创建新线程(为COM客户端请求提供服务所需),后者可能被诊断为"无法创建更多线程",而不是COM服务器中的"内存不足"(错误代码返回给客户端并由客户端观察)。

我没有证据表明它正是这样起作用的,但这是我能想到的最好的解释。看起来只是内存不足导致无法创建新线程,并被报告为"无法创建更多线程"。

相关内容

最新更新