捕获导致内存不足异常的位图
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 框架正在使用更多句柄。
问题
我目前正在尝试创建一个应用程序,当用户在他们的计算机上复制一个问题时,该应用程序将创建一个 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 框架正在使用更多句柄。