如何在不使用太多 RAM 的情况下将屏幕截图分配给图片框
How to assign screenshots to picturebox without using too much RAM
所以我有一个代码,我在其中创建位图和图形并使用 CopyFromScreen 方法截取屏幕截图,然后我继续将其分配给图片框。它在一个线程中,所以它一直在运行。问题是 RAM 消耗不断增加,如果我尝试使用 graphics.Dispose() 和 bitmap.Dispose(),它会给出一个错误,因为 pictureBox 将没有任何东西可以显示作为参考被删除了。我已经尝试将位图克隆到另一个位图并处理原始位图,但结果是一样的,RAM仍然上升。
这与其说是一个有用的项目,不如说是一个问题,但我的想法是图片框获取整个屏幕的实时副本。
我该如何解决这个问题?
代码示例:
while (run)
{
bitmap1 = new Bitmap(1920, 1080);
g = Graphics.FromImage(bitmap1);
g.CopyFromScreen(0, 0, 0, 0, size);
form.setPictureBox1(bitmap1);
g.Dispose();
bitmap1.Dispose();
GC.SuppressFinalize(this);
Thread.Sleep(500);
}
应释放所有本机对象。这包括图形和位图对象。您的代码失败,因为您在截取屏幕截图后仍想使用位图。
如果您知道自己有固定大小,那么简单的方法就是只创建一次位图,然后在每个屏幕截图中重复使用它:
Bitmap myBitmap = new Bitmap(1920, 1080); // Make sure bitmap is disposed when the form is disposed.
public MyForm()
{
myPictureBox.Image = myBitmap;
...
}
public void TakeScreenshot()
{
using(var g = Graphics.FromImage(myBitmap))
{
g.CopyFromScreen(0, 0, 0, 0, myBitmap.Size);
}
myPictureBox.Invalidate();
}
另一种方法是检查图片框是否已有图像,并在替换之前将其处理掉。
正如 John 所建议的,您应该在创建新图像之前处理掉旧图像。您也可以处理图形。
这是一个简单的例子,展示了一种可以做到这一点的方法:
private bool run = true;
private void Form1_Load(object sender, EventArgs e)
{
Thread T = new Thread(new ThreadStart(Foo));
T.IsBackground = true;
T.Start();
}
private void Foo()
{
Bitmap bmp;
Size size = Screen.PrimaryScreen.Bounds.Size;
while (run)
{
bmp = (Bitmap)pictureBox1.Image;
pictureBox1.Image = null;
if (bmp != null)
{
bmp.Dispose();
}
bmp = new Bitmap(1920, 1080);
using (Graphics g = Graphics.FromImage(bmp))
{
g.CopyFromScreen(0, 0, 0, 0, size);
}
pictureBox1.Image = bmp;
Thread.Sleep(500);
}
}
所以我有一个代码,我在其中创建位图和图形并使用 CopyFromScreen 方法截取屏幕截图,然后我继续将其分配给图片框。它在一个线程中,所以它一直在运行。问题是 RAM 消耗不断增加,如果我尝试使用 graphics.Dispose() 和 bitmap.Dispose(),它会给出一个错误,因为 pictureBox 将没有任何东西可以显示作为参考被删除了。我已经尝试将位图克隆到另一个位图并处理原始位图,但结果是一样的,RAM仍然上升。
这与其说是一个有用的项目,不如说是一个问题,但我的想法是图片框获取整个屏幕的实时副本。
我该如何解决这个问题?
代码示例:
while (run)
{
bitmap1 = new Bitmap(1920, 1080);
g = Graphics.FromImage(bitmap1);
g.CopyFromScreen(0, 0, 0, 0, size);
form.setPictureBox1(bitmap1);
g.Dispose();
bitmap1.Dispose();
GC.SuppressFinalize(this);
Thread.Sleep(500);
}
应释放所有本机对象。这包括图形和位图对象。您的代码失败,因为您在截取屏幕截图后仍想使用位图。
如果您知道自己有固定大小,那么简单的方法就是只创建一次位图,然后在每个屏幕截图中重复使用它:
Bitmap myBitmap = new Bitmap(1920, 1080); // Make sure bitmap is disposed when the form is disposed.
public MyForm()
{
myPictureBox.Image = myBitmap;
...
}
public void TakeScreenshot()
{
using(var g = Graphics.FromImage(myBitmap))
{
g.CopyFromScreen(0, 0, 0, 0, myBitmap.Size);
}
myPictureBox.Invalidate();
}
另一种方法是检查图片框是否已有图像,并在替换之前将其处理掉。
正如 John 所建议的,您应该在创建新图像之前处理掉旧图像。您也可以处理图形。
这是一个简单的例子,展示了一种可以做到这一点的方法:
private bool run = true;
private void Form1_Load(object sender, EventArgs e)
{
Thread T = new Thread(new ThreadStart(Foo));
T.IsBackground = true;
T.Start();
}
private void Foo()
{
Bitmap bmp;
Size size = Screen.PrimaryScreen.Bounds.Size;
while (run)
{
bmp = (Bitmap)pictureBox1.Image;
pictureBox1.Image = null;
if (bmp != null)
{
bmp.Dispose();
}
bmp = new Bitmap(1920, 1080);
using (Graphics g = Graphics.FromImage(bmp))
{
g.CopyFromScreen(0, 0, 0, 0, size);
}
pictureBox1.Image = bmp;
Thread.Sleep(500);
}
}