2013-05-08 38 views
3

我决定在C#中用.NET 2.0做一个简单的Windows Form项目来测试,看看究竟是什么导致了我的其他主UI应用程序中的“越来越多的内存泄漏”。Winform程序如此简单 - 但我可以回忆我的记忆吗?

我在这个简单的项目所做的是创建两种形式:Form1中&窗体2

Form1上有一个很大的按钮,在弹出的窗体2的新实例。

private void button1_Click(object sender, EventArgs e) 
{ 
    Form2 fm2 = new Form2(); 
    fm2.ShowDialog(); 
    fm2.Dispose(); 
} 

除非显示本身,直到用户决定关闭窗口,Form2才会做任何事情。

现在,当我启动应用程序,并按下Form1上的按钮时,我得到大约100 kb的内存使用跳转。我会关闭弹出窗口,再次按下按钮,并看到另一个100 kb增量。我会做约10-20次迭代。最后,我会在任务管理器中看到从6,880 KB - > 8,684 KB的跳转。现在,它最终会停在一定数量(本例中为8684 KB)。达到此之后,它不会再增加。

这里是我的问题:

我的主UI应用程序显然是一个很多比这个,如果有什么更复杂的,这种类型的内存增加最有可能只占我看到整个内存增加的部分。尽管如此,它仍然很明显,而且在一个有很多形式的项目中,这在任务管理器中看起来非常糟糕,因为它看起来像是内存泄漏。

所以首先,这是内存泄漏吗?

其次,即使它不是,有没有什么办法来防止这种情况?

+0

它停止在一个相对可预测(和低点)的事实强烈表明,这不是一个泄漏。 – dlev 2013-05-08 00:38:26

+0

您是否调用过'GC.Collect();' – ja72 2013-05-08 00:38:32

+1

您应该几乎不会手动调用GC.Collect()。 – Kevin 2013-05-08 00:40:33

回答

3

不要太在意“看起来像什么”。 .NET很好地管理内存,如果它没有收集内存,它意味着你有足够的可用内存,所以它为什么要这么麻烦?记忆在那里被使用,不被囤积和保持自由。

这不是问题,它会在需要时自行处理。

+0

我觉得我的'偏执狂'从阅读知识的时候开始正确地调用对象的Dispose(),但调用Dispose()并不一定意味着“释放资源”。经过进一步测试,看到我的应用程序达到了30 MB左右的高峰,我不再担心了。 – ykay 2013-05-08 16:34:04

+1

@ykay - 也意识到任务管理器不是监视内存使用情况的好方法。 Windows有一个复杂的内存子系统,它可以“保留”内存但实际上并不分配内存,像工作集这样的东西比内存更重要。关于Dispose,这仅用于不由运行时管理的资源,或者您想要手动控制的资源(例如确保文件在特定时间关闭,或者已经释放数据库连接)。当objet被垃圾收集时,Dispose会自动调用,但如果需要,可以直接调用它。 – 2013-05-09 14:26:52

2

显示fm2表单的代码很好,没有内存泄漏。

So first of all, is this a memory leak? 

不,事实并非如此。这是.NET如何处理托管代码。它在内存中加载对象,并在它决定这样做时释放它们。即使你的程序不需要它们,它们仍会留在内存中,直到垃圾收集器决定删除它们。

Secondly, even if it wasn't, is there any way to prevent this? 

一般情况下,使用GC.Collect时,您可能会注意到某些MB减少,特别是在处理需要多MB字节的对象时(例如图像),但这并不意味着所有资源都从内存中释放。 NET决定。