如何在不使用太多 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);
    }
}