【发布时间】:2014-11-01 19:32:23
【问题描述】:
我的代码格式如下:
while (Globals.Running)
{
if ((Form.Visible == false) || (Form.ContainsFocus == false) || (Form.Enabled == false))
{
Threading.Thread.Sleep(100);
}
else
{
Update();
Draw();
}
Application.DoEvents();
}
当我在任务管理器中查看进程时,我看到消耗的内存每秒增加 8K。
如果我注释掉Draw() 调用,内存是稳定的。因此,内存在Draw 内部泄漏。该方法如下所示:
private static void Draw()
{
BufferedGraphics.Graphics.Clear(Color.CornflowerBlue);
//Engine.Draw(BufferedGraphics.Graphics);
BufferedGraphics.Render();
++FPS;
}
所以,即使我没有画任何东西,记忆也会丢失。如果我注释掉.Clear 行,它仍然会泄漏。如果我注释掉 .Render 行,它仍然会泄漏。如果我将这两个都注释掉,它就会停止泄漏。
BufferedGraphics 在构造函数中初始化如下:
BufferedGraphics = BufferedGraphicsContext.Allocate(Graphics.FromHwnd(Form.Handle), Form.ClientRectangle);
所以,我的问题是,为什么不渲染/清除图形上下文会泄漏内存?或者这里还有其他什么在起作用?
【问题讨论】:
-
您很可能只是不了解 .NET 的内存管理是如何工作的。 .NET 使用的垃圾收集器只偶尔收集一次内存——除非“泄漏”的内存超过 10-20 MiB,否则你可能不会遇到问题。有几件事可能会在这里和那里生成一些对象,从而导致内存使用量有所增加 - 即使“游戏循环”中的
Application.DoEvents也不是最佳的。如果您正在执行实时渲染,那么看看 SharpDX/SlimDX 之类的图形库可能是值得的。 -
我明白了。我研究了 SlimDX,但由于我不需要任何密集的东西,只需要一些位图和一些文本,我认为这可以做到。我想我会像 PieterSchool 和 DJ KRAZE 所说的那样改成
Dispatcher.Invoke。 -
好吧,
Dispatcher.Invoke仍然有内存开销。换个角度想一想——你真的想要以固定的 FPS 进行实时渲染,还是想要基于事件的渲染?如果是实时的,请保持循环不变,这很好。如果基于事件,Winforms 和 WPF 都可以很好地工作,不需要仅仅为了它而使用游戏循环。 -
是的...起初我以为我需要实时,但现在...你说得对,我真的不需要它。感谢大家的帮助:)
标签: c# memory-leaks gdi