c#位图/图形内存不足

本文关键字:内存不足 图形 位图 | 更新日期: 2023-09-27 17:52:55

我正在尝试拍摄整个屏幕的快照以读取像素值。事实上,我做这件事没有任何问题。但是在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);

给出无效参数异常。我用"使用"解决了这个问题。但是现在我被这个异常卡住了

c#位图/图形内存不足

您需要在使用完一次性资源后处理它们。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
}
参考:使用实现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();
    }
}