2017-05-16 16 views
0

RenderTargetBitmapを使用して、PDFを生成するための一連のコントロールをレンダリングしています。RenderTargetBitmapのメモリリーク

public Drawing.Image RenderPageBitmap() 
{ 
    RenderTargetBitmap bit = null; 
    Drawing.Bitmap bmp = null; 
    try 
    { 
     bit = new RenderTargetBitmap(ImageSource.PixelWidth, ImageSource.PixelHeight, 96, 96, PixelFormats.Pbgra32); 

     var viewBox = GetPageXaml(); //This method loads some prebuilt XAML from an embedded resource, setting the DataContext as needed. 
     var siz = new Size(bit.PixelWidth, bit.PixelHeight); 
     viewBox.Measure(siz); 
     viewBox.Arrange(new Rect(siz)); 
     viewBox.UpdateLayout(); 

     var draw = new DrawingVisual(); 
     using (var graph = draw.RenderOpen()) 
      graph.DrawRectangle(new BitmapCacheBrush(viewBox), null, new Rect(siz)); 

     bit.Render(draw); 
     bit.Freeze(); 

     bmp = new Drawing.Bitmap(bit.PixelWidth, bit.PixelHeight, Imaging.PixelFormat.Format32bppPArgb); 

     var data = bmp.LockBits(new Drawing.Rectangle(Drawing.Point.Empty, bmp.Size), ImageLockMode.WriteOnly, Imaging.PixelFormat.Format32bppPArgb); 
     { 
      bit.CopyPixels(Int32Rect.Empty, data.Scan0, data.Height * data.Stride, data.Stride); 
     } 
     bmp.UnlockBits(data); 

     return bmp; 
    } 
    catch (Exception) 
    { 
     bmp?.Dispose(); 
     throw; 
    } 
    finally 
    { 
     bit?.Clear(); 

     GC.Collect(); 
     GC.WaitForPendingFinalizers(); 
     GC.Collect(); 
    } 
} 

でもStackOverflowの上の他の回答や問題を解決していないようです(ビットマップをクリアして、ガベージコレクションを実行するように)他のフォーラム次:次のコードセグメントは、関連するセクションです。このコードの各ループは約100MBのメモリをリークする可能性があります。つまり、私はすぐに〜2GBの32ビットプロセス制限に達します。

RenderTargetBitmap.Renderメソッドでリークが排他的に発生しているとしても、DrawingContext.DrawRectangle呼び出しでもメモリ使用量は大幅に増加しません。

この問題を解決する方法はありますか?

ここでは、JetBrainsのdotMemoryから見たメモリ使用量のスナップショットを示します。明らかに.Netヒープは正しくクリアされますが、アンマネージメモリは増加し続けます。私の検査に基づいて

Memory snapshot

+0

@Downvoter、説明してください。 –

+0

メモリリークがあると仮定しているのですか、本当にOutOfMemoryExceptionを打つのですか?私は私の答えを更新しました。ところで、私は投票しませんでした。 – CharithJ

+0

メモリリークのあるRenderTargetBitmapがどのようになっているのですか? viewBox要素はどうですか?この質問をする前に必ずメモリプロファイラを使用してください。 – Clemens

答えて

-1

drawDrawingVisualオブジェクトを割り当てます。

Render()が内部で解放されない限り、DrawingVisualオブジェクトを明示的に削除する必要があります。

+2

'DrawingVisual'はWPFクラスで、' Close'、 'Dispose'、または' Delete'メソッドはありません。 –

0

あなたはどこかにBitmapを返します。 Bitmapインスタンスが終了したら、それを破棄してください。 finallyで何をしているのかは、メモリリークがあるときは役に立たない。参照がある場合、GCはそれを収集しません。

このコードの各ループは~100MBのメモリがリークする可能性があります。つまり、 は、すぐに〜2GBの32ビットプロセス制限に達します。

メモリリークがあるとしますか?メモリリークがないかもしれません。私は良いメモリプロファイリングツールを取得し、これをテストします。

私はANTS Memory profilerを使用しましたが、それは良い(それは14日間の試用版に付属しています)。あなたのロジックを数回実行して、何かが増えている場合はInstance Listを見てください。そうであれば、保持グラフを見て、保持グラフを確認してください。それは正確に何が起こっているかを教えてくれるでしょう。メモリリークの根本原因は時々推測するのが非常に難しく、幸いにもそれには良いツールがあります。

+0

アンマネージメモリでメモリリークが発生します。 'RenderTargetBitmap'には、そのガベージコレクション手法が推奨されています。 'Bitmap'は、呼び出し側のusingブロックに囲まれています。 –

+0

@PeterDuniho 'System.Drawing.Bitmap'は絶対に' IDisposable'を実装しています:https://msdn.microsoft.com/en-us/library/8th8381z(v=vs.110).aspx –

+0

@la:私は'RenderTargetBitmap'です。あなたはメソッド宣言を表示しなかったので、あなたが記述していたコードが別の 'Bitmap'クラスを扱っていたことは私には分かりませんでした。 –

1

bit.Freeze();を削除します。ガベージコレクションはフリーズされたオブジェクトを収集しません。

関連する問題