読者です 読者をやめる 読者になる 読者になる

WPFで画像処理中にメモリが開放されず・・・

覚書程度に記載です

WPFCanvas(正確にはVisualクラス?) を RenderTargetBitmap を使って大量に画像出力していたら

エラー「メモリが足りません」
System.OutOfMemoryException: プログラムの実行を続行するための十分なメモリがありませんでした。

はー悲しい。。。


こんなのループしました。
※ブログ用に書いたから動かないかも

// 画像の読み込み
var bmp = new BitmapImage(new Uri( "ファイル名をいれてね" ));

// 画像拡大率の指定
var Scale = 1.5D;
for ( var i = 0 ; i < 1000; i++){
  var canvas = new Canvas() {
    SnapsToDevicePixels = true,
    Children = {
      ( new Func<UIElement>( ()=>{
        var re = new Image() {
          Source = bmp,
          LayoutTransform = new ScaleTransform( Scale, Scale )//画像拡大
        };
        RenderOptions.SetBitmapScalingMode( re, BitmapScalingMode.HighQuality);
        return re;
      }))(),
    },
  };
  
  canvas.Measure( new System.Windows.Size( bmp.Width * Scale, bmp.Height * Scale ) );
  canvas.Arrange( new Rect( 0, 0, bmp.Width * Scale, bmp.Height * Scale ) );
  canvas.UpdateLayout();
  
  // ファイル書き出し
  var r = new RenderTargetBitmap( (int)canvas.ActualWidth, (int)canvas.ActualHeight, 96, 96, PixelFormats.Default );
  r.Render( canvas );
  
  var img = new PngBitmapEncoder() {
  	Frames = { BitmapFrame.Create( r ) },
  };
   
  using( var stream = new FileStream( "./"+i+".png", FileMode.Create ) ) {
  	img.Save( stream );
  }

 // 強制メモリ解放!!! GC働けええええ
 // GC.Collect();
 // GC.WaitForPendingFinalizers();
 // GC.Collect();
}

メソッドを抜けるまでガンガンメモリが増えていくやつです。
メモリリークしているわけじゃなくてGC君が「後でやるよ」をし続けた結果「メモリが足りません」の流れっぽいです。

ただし GC.Collect(); だけでは足りないみたいで GC.WaitForPendingFinalizers(); の必要がありました。

こんな感じ?

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

stackoverflow.com