2012-03-08 69 views
2

我正在處理一個圓形菜單應用程序。TextureBrush導致內存泄漏,即使我配置它

在我使用位圖作爲背景之前,我必須將它裁剪爲一個圓。

好,我發現了一個代碼段用於裁剪圖像C# crop circle in a image or bitmap或:

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 ();爲了防止它,但沒有幫助。

我該怎麼辦?

+2

你是什麼意思的「導致內存泄漏」?在.net中真正泄漏內存是非常困難的。 (你基本上必須編寫一個容器類或者持有很多靜態引用。)誰告訴你它是第6行的呢? – cHao 2012-03-08 14:35:50

+0

您是否嘗試過使用()塊? – Void 2012-03-08 14:37:00

+0

這種方法是通過一些其他方法調用的,其中你有空的try catch塊,因此它吞下異常並且不會被丟棄? – formatc 2012-03-08 14:44:31

回答

0

嗯,解決了它。

正如您所說,textbrush不會導致內存泄漏。

我以前使用此代碼:

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

當我使用這一點,我的意思是配置之圖片框的給它分配一個新的位圖圖像之前防止內存泄漏。

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(); 

謝謝大家的幫忙!

5

你必須在你的代碼處置實現IDispose一切,看,它看起來像:

SourceImageCroppedImageTBG

FinalImage,因爲它是越來越不會被設置在此功能返回,但無論使用什麼FinalImage都有責任處置它。

由於PowerRoy提到,使用塊將爲您處置。

這裏是一個重構的例子使用多個使用塊:

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

+1,一個簡單的解決方案是通過將這些東西包裝在'使用'語句中 – RvdK 2012-03-08 14:37:23

+0

仍然導致內存泄漏。內存使用量每秒增加約50 MB。 – 2012-03-08 17:02:21

+0

@FatihBAKIR更重要的是GDI對象數量。從任務管理器 - 進程,視圖 - 選擇列,檢查GDI對象,觀察你的程序,同時使其失效(最小化,移動它,滾動等)。 – LarsTech 2012-03-08 17:14:10

0

唔...,似乎是一個限幅位圖的非常低效的方式。以下是我想做到這一點:

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秒。此方法僅創建兩個位圖,並確保將其中的一個與Graphics對象和GraphicsPath一起用於創建掩碼。