为什么我的Winforms程序会保留这么多虚拟内存?

时间:2011-04-13 23:28:55

标签: c# memory .net-4.0

我有一个C#/ .NET 4.0应用程序,当我启动时会显示两个带有大约十几个控件的窗口。当我运行我的程序(调试或发布无关紧要)时,在我甚至做任何事情之前,我在任务管理器/资源监视器中看到我的程序已经有超过450MB的私有内存。我意识到任务管理器不是测量内存使用情况的最可靠方法,但它是我用户最明显的方式之一。

当我运行VS2010 .NET内存分配性能分析时,对于我的程序的完整运行,它报告实际为托管对象分配了大约5MB的RAM(我的程序通常也使用一些非托管对象,但它们非常虽然没有显着的影响,但我已经禁用了它们,并且为了简化这项调查。同样,如果我在显示主窗体后从psapi.dll调用EmptyWorkingSet(),我的私有内存将降至~3.5 MB。

我已经查看了有关内存占用herehere的问题,但这些问题似乎正在处理显示为几十兆字节的程序。我的程序显示几乎 500MB ,这看起来更令人担忧。

我无法想象所有这些都来自开销;为什么VS Profiler和任务管理器之间存在如此巨大的差异?

更新:有趣的是,如果我注释掉设置ImageLists的InitializeComponent()部分,任务管理器中的数字将保持在10MB以下。我有两套PictureBoxes和ImageLists,其中PictureBox根据单选按钮组中的哪个单选按钮显示四个图像中的一个。

这些代码行似乎会引发大量内存增加:

// 
// directionImageList
// 
this.directionImageList.ImageStream = ((System.Windows.Forms.ImageListStreamer)(resources.GetObject("directionImageList.ImageStream")));
this.directionImageList.TransparentColor = System.Drawing.Color.White;
this.directionImageList.Images.SetKeyName(0, "Dir1.png");
this.directionImageList.Images.SetKeyName(1, "Dir2.png");
this.directionImageList.Images.SetKeyName(2, "Dir3.png");
this.directionImageList.Images.SetKeyName(3, "Dir4.png");
// 
// modeImageList
// 
this.modeImageList.ImageStream = ((System.Windows.Forms.ImageListStreamer)(resources.GetObject("modeImageList.ImageStream")));
this.modeImageList.TransparentColor = System.Drawing.Color.White;
this.modeImageList.Images.SetKeyName(0, "Mode1.png");
this.modeImageList.Images.SetKeyName(1, "Mode2.png");
this.modeImageList.Images.SetKeyName(2, "Mode3.png");

我正在使用ImageLists,所以我可以使用透明度。模式图像为100x100,每个占用<26KB的磁盘空间。方向图像默认为208x277,磁盘大约为75KB。我知道png是一种压缩格式,但即使在内存中未压缩,我也不会期望这七张图片有数百兆字节。

我是否知道一些效率低下的问题,是否有另一种动态显示透明图片的方法?

结论:使用ImageList类可能会出现问题。有时它会丢失alpha通道,这导致我的程序保留了比它需要的更多内存。它也减慢了最初绘制主窗体的时间(在跑步时和在设计师中)。

将两个ImageLists转储到一个更健康的10MB RAM中。感谢大家的所有建议!

5 个答案:

答案 0 :(得分:2)

我对这个问题的经验是,我在imageList中有24位图像,而我在图像列表的设置中设置了32位选项。

我在图像列表的属性中设置了24位,问题已经消失。这似乎是一个人应该发布到MS =)的错误

抱歉我的英文。

答案 1 :(得分:1)

.Net框架设计为在可用资源的情况下尽可能快地运行。应用程序将继续消耗越来越多的内存,因为它在请求时(并且随时可用)仅在您专门调用垃圾收集器时或当另一个应用程序需要占用资源时才放弃。

最小化应用程序,您应该看到应用程序使用多少内存的更好表示。

如果您再回到使用它,它将保持在较低的资源状态,直到它被使用并再次消耗。再次最小化它,看看实际上(不)再次使用了多少。这是内置于.net框架内存管理系统。

答案 2 :(得分:1)

有人解释了内存从34 MB跳到145 MB的几个原因:Finding the true memory footprint of a Windows application

答案 3 :(得分:0)

首先,你试过Debug Diag吗?它将分析你的进程的转储并提供一些漂亮的图形内存,这可能有助于你找出谁分配了所有内存。

另外,请检查以确保编译的.exe或任何引用/加载的程序集都不是很大 - 完全有可能所有~500MB只是加载dll。如果(例如)大型资源已嵌入到程序集中,则可能会发生这种情况。

答案 4 :(得分:0)

png已经具有透明度了。只需将白色设为透明色并保存图像即可。然后正常使用它们。