TextureBrush вызывает утечку памяти, даже если я ее утилизирую - PullRequest
2 голосов
/ 08 марта 2012

Я работаю над приложением кругового меню.

Прежде чем использовать растровое изображение в качестве фона, я должен обрезать его в виде круга.

Ну, я нашел фрагмент кода для обрезки картинки 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;
}

Но код вызывает утечку памяти через некоторое время в строке 6.

Хорошо, я попытался добавить TB.Dispose (); чтобы предотвратить это, но это не помогло.

Что мне делать?

Ответы [ 3 ]

5 голосов
/ 08 марта 2012

Вам нужно избавиться от всего, что реализует IDispose, и, глядя на ваш код, это выглядит так:

SourceImage, CroppedImage, TB, G

FinalImage не утилизируется в этой функции, поскольку она возвращается, но все, что использует FinalImage, несет ответственность за ее удаление.

Как упоминалось в PowerRoy, использование блоков потребует утилизации дляyou.

Вот рефакторированный пример использования нескольких блоков:

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;
}
0 голосов
/ 09 марта 2012

Хорошо, решено.

Как вы сказали, textbrush не вызывает утечку памяти.

Я использовал этот код:

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

Когда я использовал это, я имел в виду удаление изображения 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();

Спасибо всем за помощь!

0 голосов
/ 08 марта 2012

Хм ... это очень неэффективный способ отсечения растрового изображения. Вот как я это сделаю:

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;
    }
}

В данный момент причина утечки памяти, вероятно, заключается в том, что вы забыли избавиться от всех этих временных Bitmap s. Этот метод создает только два растровых изображения и обеспечивает удаление одного из них вместе с объектом Graphics и GraphicsPath, используемыми для создания маски.

...