1

操作系统:Windows 7 嵌入式

内存:1 GB

分页文件大小:500 MB

剩余磁盘空间:~1 GB

.NET:2.0

我正在开发一个在 Windows 7 Embedded 上运行的用 C# 编写的 .NET 2.0 Winforms 应用程序,其中系统只有 1 GB 的 RAM,并且可用磁盘空间相当有限(~1 GB)。我们正在从 Windows XP Embedded 迁移到 Windows 7 Embedded,虽然我们的程序在 Windows XP 上运行良好,但由于 Windows 7 上的内存不足异常,它已经失败了好几次。我们添加了一个 500 MB 的页面文件,因为失败( Windows 7 Embedded 的默认值似乎是 0MB 的页面文件大小)。但是,由于我们已将由程序提交的内存增加引起的内存不足异常缩小,因此系统提交限制可能会在足够长的时间内达到,即使是分页文件也是如此。我们无法快速将硬件迁移到更合适的位置,

使用 SysInternals VMMap 工具,我们可以看到程序的虚拟内存中线程堆栈的数量随着时间的推移缓慢增加,最终在程序提交的内存导致系统超出其提交限制时导致失败。线程堆栈增加的原因已与 .NET 2.0 ThreadPool 隔离,由于某种原因,它会随着时间的推移创建净正数的线程。我们认为这是因为在我们的代码中过度使用了 System.Timers.Timer 类,每个实例都在 ThreadPool 上运行其计时器已过事件处理程序,尽管仍然不清楚为什么 ThreadPool 会保留这么多线程,即使在假设它们并不总是被计时器回调使用。其中一些事件处理程序处理信息的时间超过了 ThreadPool 线程的理想时间,

我们已经为这个问题想出了几种可能的解决方案,包括限制 ThreadPool 工作线程的数量,将运行时间较长的计时器回调换成线​​程,以及迁移到更高版本的 .NET。最后一个解决方案假定 ThreadPool 管理器的优化已经在 .NET 的迭代中进行,这可能有助于缓解问题。是否还有其他我们遗漏的明显(或不明显)解决方案?

编辑:在进一步检查中,生成并保留的 ThreadPool 线程具有以下调用堆栈:

ntdll!KiFastSystemCallRet 
ntdll!ZwWaitForSingleObject+c 
KERNELBASE!WaitForSingleObjectEx+98 
kernel32!WaitForSingleObjectExImplementation+75 
mscorwks!PEImage::LoadImage+1af 
mscorwks!CLREvent::WaitEx+117 
mscorwks!CLREvent::Wait+17 
mscorwks!ThreadpoolMgr::SafeWait+73 
mscorwks!ThreadpoolMgr::WorkerThreadStart+11c 
mscorwks!Thread::intermediateThreadProc+49 
kernel32!BaseThreadInitThunk+e 
ntdll!__RtlUserThreadStart+70 
ntdll!_RtlUserThreadStart+1b 
4

0 回答 0