C# Bitmap/Graphics 内存不足
C# Bitmap/Graphics Out of Memory
我正在尝试拍摄整个屏幕的快照以读取像素值。其实我这样做没有任何问题。但是在恰好 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);
给出无效参数异常。我用 "using" 解决了它。但现在我陷入了这个例外。
您需要在使用完一次性资源后对其进行处置。 Bitmap
class 实现了 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
}
Reference: 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();
}
}
我正在尝试拍摄整个屏幕的快照以读取像素值。其实我这样做没有任何问题。但是在恰好 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);
给出无效参数异常。我用 "using" 解决了它。但现在我陷入了这个例外。
您需要在使用完一次性资源后对其进行处置。 Bitmap
class 实现了 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
}
Reference: 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();
}
}