捕获导致内存不足异常的位图

Capturing bitmaps causing Out Of Memory exception

问题

我目前正在尝试创建一个应用程序,当用户在他们的计算机上复制一个问题时,该应用程序将创建一个 gif/video(尚未决定)的用户屏幕。这显然意味着我需要通过计时器定期创建屏幕截图。

问题是在 25 秒后(总是 25 秒),我收到一个错误,说系统内存不足。

Exception thrown: 'System.OutOfMemoryException' in System.Drawing.dll

Additional information: Out of memory.

我的代码

下面是 Timer Tick 事件中的代码:

Private DebugVid As New List(Of IntPtr)

Private Sub tmrDebug_Tick(sender As Object, e As EventArgs) Handles tmrDebug.Tick

    Dim CurrentScreen As Screen = Screen.PrimaryScreen
    For Each SCR As Screen In Screen.AllScreens
        If SCR.Bounds.Contains(MousePosition) Then
            CurrentScreen = SCR
        End If
    Next

    Using ScreenGrab As New Bitmap(CurrentScreen.Bounds.Width, CurrentScreen.Bounds.Height)
        Using g As Graphics = Graphics.FromImage(ScreenGrab)
            g.CopyFromScreen(New Point(CurrentScreen.Bounds.X, CurrentScreen.Bounds.Y), New Point(0, 0), ScreenGrab.Size)
            g.DrawImage(My.Resources.MyCursor, New Point(MousePosition.X - CurrentScreen.Bounds.X, MousePosition.Y))
        End Using
        DebugVid.Add(ScreenGrab.GetHbitmap())
    End Using

    GC.Collect()
End Sub

第一部分只是定义光标在哪个屏幕上,所以我知道要为哪个屏幕创建位图。

第二部分创建位图,对其应用屏幕截图,在鼠标位置绘制光标,最后将整数指针存储在列表中。

一旦用户单击按钮停止录制,它就会将其转换为 gif(此时)。

抛出异常的代码部分是以下行:

DebugVid.Add(ScreenGrab.GetHbitmap())

感谢任何帮助。

这可能是大量非托管 GDI 句柄和位图数据要保存在内存中。如果在 25 秒后您耗尽了可用的句柄,甚至只是可用的进程内存,我一点也不会感到惊讶。您可能需要考虑在录制时将每个帧保存到磁盘。然后在录制完成后,将各个图像处理成 gif。

根据 MSDN,一个进程可用的 GDI 句柄数范围从 256 到 65536,具体取决于操作系统和配置。您截取的每个屏幕截图都至少 一个句柄,您的应用程序和 .net 框架正在使用更多句柄。