新手头顶:为什么我自制的屏幕录像机崩溃了?(c# 和 windows 形式)

Newb over head: Why is my home made screen recorder crashing?(c# and windows forms)

[已解决] Ofir 的解决方案开箱即用。目前 运行 24 f/s 五分钟。

我正在尝试保存屏幕上的图像。

基本上我的问题是,当我降低 Thread.sleep(以创建合适的帧速率)时,程序崩溃了。 thread.sleep 越接近 0,程序崩溃得越快,但我什至找不到问题,因为我从来没有处理过这种东西(如果是 unity3d,我会全力以赴)。

void ScreenCapture()//this is from a youtube tutorial
    {
        while (true)
        {
            Bitmap bm = new Bitmap((int)Math.Round(Screen.PrimaryScreen.Bounds.Width * 1.5), (int)Math.Round(Screen.PrimaryScreen.Bounds.Height * 1.5));
    //I don't know why I had to multipyly these by 1.5, but it made the screen fit properly.
            Graphics g = Graphics.FromImage(bm);
            g.CopyFromScreen(0, 0, 0, 0, bm.Size);
            pictureBox.Image = bm;
            Thread.Sleep(250);
        }
    }

    private void button2_Click(object sender, EventArgs e)
    {
        Thread t = new Thread(ScreenCapture);
        t.Start();
    }

我也遇到了一些甜蜜的错误。

'System.ComponentModel.Win32Exception' 类型的未处理异常发生在 System.Drawing.dll

错误代码:-2147467259

我构建了一个 try-catch(我对此知之甚少),但在几次测试后它也坏了,让我看看我是否能得到那个日志。

    System.ComponentModel.Win32Exception(0x80004005): The operation completed successfully as System.Drawing.Graphics.CopyFromScreen(Int32 sourceX, Int32 sourceY, Int32 destinationX,Int32 destinationY, Size blockRegionSize)
 at Screen_Recorder.Form1.ScreenCapture() in C:Users\Jupiter\Desktop\visual studio experiments\Screen Recorder\ScreenRecorder\Form1.cs:line 35

如果我然后点击确定它说:

System.ArgumentException: Parameter is not valid.
 at System.Drawing.Bitmap..ctor(Int32 width, Int32 height, PixelFormat format)
 at System.Drawing.Bitmap..ctor(int32 width, Int32 height)
 at Screen_Recorder.Form1.ScreenCapture() C:Users\Jupiter\Desktop\visual studio experiments\Screen Recorder\ScreenRecorder\Form1.cs:line 32

然后它将无限重复该错误。

无论如何,我要睡觉了,明天我会再次开始,但在此之前的任何建议将不胜感激!

你有内存泄漏。

GraphicsBitmap 是一次性物品,用完后应该丢弃。
您只能将 Graphics 放在 using 块中,并且在循环的每次迭代中都应处理最后一个位图。
因此,您的代码应如下所示:

private void ScreenCapture()
{
    while (true)
    {
        var bm = new Bitmap((int)Math.Round(Screen.PrimaryScreen.Bounds.Width * 1.5), 
                           (int)Math.Round(Screen.PrimaryScreen.Bounds.Height * 1.5));
        using (Graphics g = Graphics.FromImage(bm)) g.CopyFromScreen(0, 0, 0, 0, bm.Size);

        // As per the comment by HansPassant - the following would cause
        // a thread race with the UI thread.
        //this.pictureBox1.Image?.Dispose();
        //this.pictureBox1.Image = bm;

        // Instead we use beginInvoke to run this on the UI thread
        Action action = () =>
            {
                this.pictureBox1.Image?.Dispose();
                this.pictureBox1.Image = bm;
            };

        this.BeginInvoke(action);

        Thread.Sleep(250);
    }
}

这个循环永远不会结束(因为 while (true)),也许你应该考虑添加一个 CancelationToken 并使用 Task 而不是 Thread

最后一件事,您应该在完成图片框后将其处理掉。