C#内存泄漏GDI + [英] C# Memory leak in GDI+

查看:197
本文介绍了C#内存泄漏GDI +的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

大家好!

我正在编写程序来测试内存泄漏。这是我的代码:

Hello everyone!
I'm writing program to test memory leak. This is my code:

public partial class Form1 : Form
   {
       Pen p = new Pen(Color.Red, 1.0f);
       Random d = new Random();

       public Form1()
       {
           DoubleBuffered = true;
           InitializeComponent();
           timer1.Start();
       }

       private void OnTimerTick(object sender, EventArgs e)
       {
           Invalidate();
       }

       private void OnForm1Paint(object sender, PaintEventArgs e)
       {
           Graphics g = e.Graphics;
           g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
           for (int i = 0; i < 100; i++)
           {
                g.DrawLine(
                    p,
                    d.Next(Width),
                    d.Next(Height),
                    d.Next(Width),
                    d.Next(Height));
           }
       }
   }



当我运行这个程序并查看Windows任务管理器中的内存时,我看到我的程序的内存增加。我不明白为什么会这样?有人可以帮助我吗?

对不起我的英文!


When i run this program and look at memory in "Windows task manager", I see memory of my program is increased .I do not understand why this is so? Can someone help me?
Sorry for my English!

推荐答案

好的,每个人都专注于笔。这不是你发布的代码中的问题。



好​​吧,有一个小问题,你在应用程序终止之前没有处理Pen。这将导致手柄泄漏并最终破坏Window但你必须一遍又一遍地运行这个应用程序,数千次,在此之前。



问题是您正在查看任务管理器以查看您的应用程序使用了多少内存。这是错误的地方。它显示了.NET CLR为您的应用程序保留了多少内存,而不是它使用了多少。



如果你想看看实际使用了多少,使用PerfMon和.NET内存计数器或CLR内存分析器来查看实际使用的内容。
OK, everyone is focused on the Pen. That's not the problem in the code you posted.

Well, there is one small problem where you're not disposing the Pen before your app terminates. This will lead to a handle leak and eventually break Window but you have to run this app over and over again, thousands of times, before that happens.

The problem is that you're looking at Task Manager to see how much memory your app is using. That's the WRONG place to look. It's showing you how much memory the .NET CLR has RESERVED for your application, not how much it's using.

If you want to see how much is actually is use, use PerfMon and the .NET memory counters or a CLR memory profiler to see what's actually being used.


GDI有很多非托管资源的例子,开发人员负责在使用后进行处理。

在你的例子中,我看到笔和图形。

你没有创建的图形,所以你不必释放它。

然而,笔需要释放或释放。



尝试将它放入事件处理程序并在绘制后将其丢弃。

进行测试并告诉我如果你有一些改进。'
GDI has great examples of unmanaged resources which developers are responsible for disposing after using.
In your example I see Pen and Graphic.
The graphic you are not creating so you dont have to release it.
The pen however, needs to be freed or released.

Try to put it in the eventhandler and dispose it after you draw.
Make the test and let me know if you have some improvement.'


除了解决方案1:



你有两个选择:
In addition to Solution 1:

You have two options:




  1. 您可以按照自己的方式创建 Pen 的实例,并将其置于此<$ c $中C> Form.Disp ose 方法: http:// msdn。 microsoft.com/en-us/library/aw58wzka%28v=vs.110%29.aspx [ ^ ]。



    这是设计用于根据他们的父子关系在一组UI元素(或您想要自己设计的其他对象)中进行链处理。
  2. 此外,您可以在使用它的地方创建笔的实例(在您重写的 OnPaint 方法或事件的处理程序 Paint 并在使用后立即处置。最好的方法是使用使用语句:


  1. You can create your instance of Pen the way you do and dispose it in this Form.Dispose method: http://msdn.microsoft.com/en-us/library/aw58wzka%28v=vs.110%29.aspx[^].

    This is the approach designed to chain disposal in a set of UI elements (or some other objects you would want to design yourself) according to their parent-child relationships.
  2. Also, you can create an instance of your pen where you use it (in your overridden OnPaint method or your handler of the event Paint and dispose immediately after use. The best way to do it is using the using statement:
using (Pen pen = new Pen(Color.Red, 1.0f))
{
    for (int i = 0; i < 100; i++)
            {
                 g.DrawLine(
                     p, 
                     d.Next(Width), 
                     d.Next(Height), 
                     d.Next(Width), 
                     d.Next(Height));
            }
} // pen.Dispose is automatically called here



即使抛出异常,也不会调用 pen.Dispose 。请参阅: http://msdn.microsoft.com/en-us/library/yh598w02.aspx [ ^ ]。


Not that pen.Dispose will be called even of an exception is thrown. Please see: http://msdn.microsoft.com/en-us/library/yh598w02.aspx[^].





使用GDI时,通常会出现非托管内存泄漏。简单的规则是:注意所有对象;检查是否实现 System.IDisposable 。如果他们这样做,请确保您处置它们。另请参阅: http://msdn.microsoft.com/en -us / library / system.idisposable%28v = vs.110%29.aspx [ ^ ]。



此外,可能存在管理内存泄漏,但这可能是错误设计的结果。这是一个不同的故事...



-SA



Unmanaged memory leaks are usual when you use GDI. The simple rule is: watch out for all objects; check up if they implement System.IDisposable. If they do, make sure you dispose them. See also: http://msdn.microsoft.com/en-us/library/system.idisposable%28v=vs.110%29.aspx[^].

Also, managed memory leak is possible, but that could be a result of wrong design. This is a different story…

—SA


这篇关于C#内存泄漏GDI +的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆