C#位图/图形内存不足

时间:2016-06-29 09:30:04

标签: c# memory bitmap graphic

我正在尝试拍摄整个屏幕的快照以读取像素值。其实我这样做没有任何问题。但是在完成214个快照之后,我的内存异常就出现了。

Bitmap ScreenShot = new Bitmap(Screen.PrimaryScreen.Bounds.Width,
  Screen.PrimaryScreen.Bounds.Height);

public Bitmap TakeSnapshot()
{
    Graphics graphic = null;
    Rectangle rect = new Rectangle(0, 0, Screen.PrimaryScreen.Bounds.Width,
      Screen.PrimaryScreen.Bounds.Height);

    using (graphic = Graphics.FromImage(ScreenShot))
    {
        graphic.CopyFromScreen(Screen.PrimaryScreen.Bounds.X, Screen.PrimaryScreen.Bounds.Y, 
            0, 0, 
            ScreenShot.Size, 
            CopyPixelOperation.SourceCopy);
    }

    return ScreenShot.Clone(rect,System.Drawing.Imaging.PixelFormat.Format32bppArgb);
}

我正在使用此方法与计时器

Bitmap bmp = TakeSnapshot();
        var c = bmp.GetPixel(0,0);

它给出了无效的参数异常。我用“使用”解决了它。但现在我坚持这个例外。

1 个答案:

答案 0 :(得分:1)

一旦您完成了一次性资源的处理,您就需要处置它们。 Bitmap类实现IDisposable - 因此它是可支配资源。正确的模式不是

Bitmap bmp = TakeSnapshot();
var c = bmp.GetPixel(0,0);

这样的东西
Bitmap bmp = null;
try
{
  bmp = TakeSnapshot();
  var c = bmp.GetPixel(0,0);
  // any more work with bmp
}
finally
{
  if (bmp != null)
  {
    bmp.Dipose();    
  }
}

或简称(最好):

using(Bitmap bmp = TakeSnapshot())
{
  var c = bmp.GetPixel(0,0);
  // any more work with bmp
}
  

参考:Using Objects That Implement IDisposable

修改

您可以轻松模拟问题:

public class TestDispose : IDisposable
{
    private IntPtr m_Chunk;
    private int m_Counter;
    private static int s_Counter;

    public TestDispose()
    {
        m_Counter = s_Counter++;
        // get 256 MB
        m_Chunk = Marshal.AllocHGlobal(1024 * 1024 * 256);
        Debug.WriteLine("TestDispose {0} constructor called.", m_Counter);
    }

    public void Dispose()
    {
        Debug.WriteLine("TestDispose {0} dispose called.", m_Counter);
        Marshal.FreeHGlobal(m_Chunk);
        m_Chunk = IntPtr.Zero;
    }
}

class Program
{
    static void Main(string[] args)
    {
        for(var i = 0; i < 1000; i ++)
        {
            var foo = new TestDispose();
        }
        Console.WriteLine("Press any key to end...");
        Console.In.ReadLine();
    }
}