2017-03-16 30 views
1

タスク:私は2つのモニタを持っています。そして、#1で#2で何が起こっているかを示す必要があります。言い換えれば、最初のモニターは2番目のリフレクターに過ぎません。WPFアプリケーションのBitmapSourceを使用したOutOfMemory例外

現在の解決策:〜100msごとにスクリーンショットを作成し直して再描画します。最初の2番目の画面から自分の "反射" を実行するためにその後

private BitmapSource MakeScreenshot(Screen screen) 
    { 
     using (var screenBmp = new Bitmap(screen.Bounds.Width, screen.Bounds.Height, PixelFormat.Format32bppArgb)) 
     { 
      using (var bmpGraphics = Graphics.FromImage(screenBmp)) 
      { 
       bmpGraphics.CopyFromScreen(screen.Bounds.X, screen.Bounds.Y, 0, 0, screen.Bounds.Size); 

       return 
        Imaging.CreateBitmapSourceFromHBitmap(
         screenBmp.GetHbitmap(), 
         IntPtr.Zero, 
         Int32Rect.Empty, 
         BitmapSizeOptions.FromEmptyOptions()); 
      } 
     } 
    } 

私はusetスタート(...)メソッド: 次のメソッドは、キャプチャスクリーンショットを担当して

public void Start(int delay, int period) 
    { 
     if (_timer != null) throw new InvalidOperationException(); 

     _timer = new System.Threading.Timer(
      _ => 
      { 
       _placeholder 
        .Dispatcher 
        .Invoke(() => 
        { 
         _placeholder.Source = MakeScreenshot(_targetScreen); // re-render new screenshot 
        }); 
      }, 
      null, 
      delay, 
      period); 
    } 

問題:約30〜40秒後には、OutOfMemoryExceptionで失敗します。私はここにいくつかの記事を調査しましたが、私の問題に関しては何も見つかりませんでした。

Imaging.CreateBitmapSourceFromHBitmap(
    screenBmp.GetHbitmap(), // < here 
    IntPtr.Zero, 
    Int32Rect.Empty, 
    BitmapSizeOptions.FromEmptyOptions()); 

あなたはあなたがscreenBmp.GetHbitmap()を呼び出した後、GDIビットマップが使用するメモリを解放する必要があります:あなたがここにメモリリークが発生するのである

+0

もうスクリーンショットを整理してもらえませんか? – lokusking

+0

@ lokuskingまずはIDisposableにUsing(...)を使います。 BitmapSourceはIDisposableを実装せず、.Clean()メソッドのようなものを持たない。 –

答えて

3

。これを次のように変更してください。

private BitmapSource MakeScreenshot(Screen screen) 
{ 
    using (var screenBmp = new Bitmap(screen.Bounds.Width, screen.Bounds.Height, PixelFormat.Format32bppArgb)) 
    { 
     using (var bmpGraphics = Graphics.FromImage(screenBmp)) 
     { 
      bmpGraphics.CopyFromScreen(screen.Bounds.X, screen.Bounds.Y, 0, 0, screen.Bounds.Size); 
      var handle = screenBmp.GetHbitmap(); 
      try { 
       return 
        Imaging.CreateBitmapSourceFromHBitmap(
         handle, 
         IntPtr.Zero, 
         Int32Rect.Empty, 
         BitmapSizeOptions.FromEmptyOptions()); 
      } 
      finally { 
       DeleteObject(handle); 
      } 
     } 
    } 
} 

[System.Runtime.InteropServices.DllImport("gdi32.dll")] 
public static extern bool DeleteObject(IntPtr hObject); 

これ以上のリークはありません。

+0

ありがとうございました。 –

関連する問題