简体   繁体   English

即使我将其丢弃,TextureBrush也会导致内存泄漏

[英]TextureBrush Causes Memory Leak, Even If I Dispose It

I am working on a circular menu application. 我正在研究圆形菜单应用程序。

Before I use a bitmap as background, I must crop it as a circle. 在使用位图作为背景之前,必须将其裁剪为圆形。

Well, I found a code snippet for cropping the picture C# crop circle in a image or bitmap or: 好吧,我找到了一个代码片段,用于在图像或位图中裁剪图片C#裁剪圆,或者:

public System.Drawing.Image x(string sourceFile, int circleUpperLeftX, int circleUpperLeftY, int circleDiameter)
{
    Bitmap SourceImage = new Bitmap(System.Drawing.Image.FromFile(sourceFile));
    Rectangle CropRect = new Rectangle(circleUpperLeftX, circleUpperLeftY, circleDiameter, circleDiameter);
    Bitmap CroppedImage = SourceImage.Clone(CropRect, SourceImage.PixelFormat);
    TextureBrush TB = new TextureBrush(CroppedImage);
    Bitmap FinalImage = new Bitmap(circleDiameter, circleDiameter);
    Graphics G = Graphics.FromImage(FinalImage);
    G.FillEllipse(TB, 0, 0, circleDiameter, circleDiameter);
    return FinalImage;
}

But the code causes memory leak after a while in line 6. 但是代码在第6行过一段时间后会导致内存泄漏。

Well, I tried adding TB.Dispose(); 好吧,我尝试添加TB.Dispose();。 to prevent it but, that didn't help. 防止它,但这没有帮助。

What should I do? 我该怎么办?

You need to dispose everything that implements IDispose , and looking at your code, it looks like: 您需要处理实现IDispose所有内容,并查看您的代码,如下所示:

SourceImage , CroppedImage , TB , G SourceImageCroppedImageTBG

FinalImage does not get disposed in this function since it is getting returned, but whatever is using FinalImage has the responsibility to dispose of it. 由于会返回FinalImage ,因此不会将其丢弃,但是无论使用FinalImage有责任对其进行处置。

As PowerRoy mentioned, using blocks will take of the disposing for you. 如PowerRoy所述,使用块将为您处理。

Here is a refactored example using multiple using blocks: 这是一个使用多个using块的重构示例:

public Image CreateFinalImage(string sourceFile, int circleUpperLeftX, int circleUpperLeftY, int circleDiameter) {
  Bitmap finalImage = new Bitmap(circleDiameter, circleDiameter);
  Rectangle cropRect = new Rectangle(circleUpperLeftX, circleUpperLeftY, circleDiameter, circleDiameter);

  using (Bitmap sourceImage = new Bitmap(System.Drawing.Image.FromFile(sourceFile)))
  using (Bitmap croppedImage = sourceImage.Clone(cropRect, sourceImage.PixelFormat))
  using (TextureBrush tb = new TextureBrush(croppedImage))
  using (Graphics g = Graphics.FromImage(finalImage)) {
    g.FillEllipse(tb, 0, 0, circleDiameter, circleDiameter);
  }

  return finalImage;
}

Hm... that appears to be a very inefficient way of clipping a bitmap. 嗯...这似乎是裁剪位图的一种非常低效的方式。 Here's how I'd do it: 这是我的处理方式:

public Image x(string sourceFile, int circleUpperLeftX, int circleUpperLeftY, int circleDiameter) {
    using(Bitmap sourceImage = new Bitmap(sourceFile), GraphicsPath p = new GraphicsPath()) {
        Bitmap destImage = new Bitmap(circleDiameter, circleDiameter, sourceImage.PixelFormat);

        p.AddEllipse(circleUpperLeftX, circleUpperLeftY, circleDiameter, circleDiameter);

        using(Graphics g = Graphics.FromImage(destImage)) {
            g.SetClip(p);
            g.DrawImageUnscaled(sourceImage, 0, 0);
        }

        return destImage;
    }
}

Right now, the reason for your memory leak is probably forgetting to dispose all those temporary Bitmap s. 现在,内存泄漏的原因可能是忘记处置所有这些临时Bitmap This method only creates two bitmaps and makes sure to dispose one of them, along with the Graphics object and the GraphicsPath used to create the mask. 此方法仅创建两个位图,并确保将其中之一以及用于创建遮罩的Graphics对象和GraphicsPath一起放置。

Well, Solved It. 好了,解决了。

As you said, textbrush is not causing the memory leak. 如您所说,textbrush不会导致内存泄漏。

I used to use this code: 我曾经使用以下代码:

pictureBox1.Image = menu.Draw(bos, new Point(Cursor.Position.X - Left, Cursor.Position.Y - Top), (int)DateTime.Now.Subtract(sabit).TotalMilliseconds / 4);

When I used this, I mean Disposing PictureBox's Image before assigning a new Bitmap to it prevented the memory leak. 当我使用它时,我的意思是在分配一个新的位图之前先处理PictureBox的图像,以防止内存泄漏。

Bitmap result = menu.Draw(bos, new Point(Cursor.Position.X - Left, Cursor.Position.Y - Top), (int)DateTime.Now.Subtract(sabit).TotalMilliseconds / 4);
        if (pictureBox1.Image != null)
            pictureBox1.Image.Dispose();
        pictureBox1.Image = (Image)result.Clone();
        result.Dispose();

Thank you all for your help! 谢谢大家的帮助!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 内存泄漏问题:处置还是不处置托管资源? - Memory leak problems: dispose or not to dispose managed resources? TextureBrush内存不足异常 - TextureBrush Out of Memory Exception 为什么我没有内存泄漏.Dispose()我.save()的位图到MemoryStream? - Why is there a memory leak when I do not .Dispose() Bitmaps that I .Save() to a MemoryStream? 在Listbox中处理WPF中的图像(内存泄漏) - Dispose of Image in WPF in Listbox (memory leak) 如果处理失败,是否有可能永久泄漏 memory? - Is it possible to have permanent memory leak if failed to dispose? 具有 CancellationTokenSource 和超时 memory 的通道在处理后泄漏 - Channels with CancellationTokenSource with timeout memory leak after dispose 调用subject.OnCompleted()是否会整理/调用处置/不泄漏内存,还是我自己必须在IDisposable上调用处置? - Will calling subject.OnCompleted() tidy up/ call dispose/not leak memory or do I have to call dispose on the IDisposable myself? 绑定到列表导致内存泄漏 - Binding to list causes memory leak SqlCommand.Dispose()没有在其中部署SqlParameters - 内存泄漏 - C#.NET - SqlCommand.Dispose() not disposing the SqlParameters in it - Memory Leak - C#.NET C#位图导致内存泄漏 - C# bitmaps causes memory leak
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM