截图程序各种内存泄漏,问题在哪里?
vb.net吧
全部回复
仅看楼主
level 13
Nukepayload2 楼主
'测试时用的是这个。wpf的一个Rectangle里刷了截下的图
Public Shared Overloads Function GetScreenSnapshot() As Brush
Dim rc As Rectangle = SystemInformation.VirtualScreen
Using bitmap As New Bitmap(rc.Width, rc.Height, PixelFormat.Format32
bp
pArgb)
Using g As Graphics = Drawing.Graphics.FromImage(bitmap)
g.CopyFromScreen(rc.X, rc.Y, 0, 0, rc.Size, CopyPixelOperation.SourceCopy)
End Using
End Using
Return New ImageBrush(ToBitmapSource(bitmap))
End Function
'原始版本
Public Shared Overloads Function GetScreenSnapshot() As Bitmap
Dim rc As Rectangle = SystemInformation.VirtualScreen
Using bitmap As New Bitmap(rc.Width, rc.Height, PixelFormat.Format32bppArgb)
Using g As Graphics = Graphics.FromImage(bitmap)
g.CopyFromScreen(rc.X, rc.Y, 0, 0, rc.Size, CopyPixelOperation.SourceCopy)
End Using
End Using
Return bitmap
End Function
'类型转换器
Public Shared Function ToBitmapSource(bmp As Bitmap) As BitmapSource
Dim returnSource As BitmapSource = Interop.Imaging.CreateBitmapSourceFromHBitmap(bmp.GetHbitmap(), IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions())
Return returnSource
End Function
2013年08月12日 14点08分 1
level 13
Nukepayload2 楼主
改一句 g.CopyFromScreen(Left, Top, 0, 0, Forms.Screen.PrimaryScreen.Bounds.Size)
这个Rectangle加了磨砂玻璃特效,所以截下来的图这样用可以仿制win7玻璃特效
2013年08月12日 14点08分 2
level 13
Nukepayload2 楼主
还有,wpf的绘制似乎都会推迟。
截图前Opacity = 0
截图后Opacity = 1
结果截出的图里还是有当前窗体。
2013年08月12日 14点08分 3
level 13
Nukepayload2 楼主
目前我想到的解决绘制延迟的办法是暂时设置Visibility,中途延时截图。这样做截出来的图没问题,但闪烁明显。
2013年08月12日 15点08分 4
level 13
Nukepayload2 楼主
内存泄漏非常可怕,不到1分钟就只剩百分之5的ram可用了。
2013年08月12日 15点08分 5
最奇怪的是,每个函数都强行gc.collect,结果不仅内存泄漏无任何缓解迹象,而且更卡了。
2013年08月12日 15点08分
level 6
总觉得不是内存泄露,而是你的程序里,有什么地方还存在着引用。GC那个其实不要老是去调用,本来就是个费时的操作,系统才会把它扔到背景线程去做的。
2013年09月02日 04点09分 6
跟这段代码有关的就是一个Rectangle的Background属性。按理说给Background赋值会让新的顶掉旧的。
2013年09月04日 12点09分
给那个属性赋值时所有带IDisposable的对象都手动销毁了。
2013年09月04日 12点09分
level 6
仔细看了看,你这都using了,bitmap在范围外是怎么能用的啊?总觉得有点奇怪。
2013年09月02日 04点09分 7
确实能用。不会空引用
2013年09月02日 14点09分
我发完帖子就把代码改了一下,创建位图和画布放在窗体loaded执行,手动释放它们在窗体closing执行,其余代码不变。结果还是内存泄漏。
2013年09月02日 14点09分
level 10
我做的截图程序是用新建一个内存流(MemoryStream)来装载图片的,等到不用的时候就关闭清除这个内存流
最好自己指定图片数据的容器,我一直都不太敢相信.NET后台的自动处理
2013年09月03日 12点09分 8
这个想法不错。声音图片什么的放入内存流可以低延迟,还可以控制何时销毁。
2013年09月04日 12点09分
level 10
妈蛋,我的回帖被系统删了吗?
2013年09月03日 12点09分 9
level 8
copyScreen这个函数有bug,不是你的程序的问题。我用API函数截图,getDC(0)可以获得整个屏幕的DC
2013年09月08日 03点09分 10
那我自己实现这个函数试试。
2013年09月08日 12点09分
回复 Nukepayload2 :我以前写过这个程序,每秒截图25帧左右,我一开始用CopyScreen也遇到了同样的问题。然后我改用API自己实现,性能类似,没有内存泄露问题。
2013年09月08日 12点09分
回复 jimmyfluore :wpf不支持涉及控件句柄的操作,因为wpf控件无句柄。
2013年09月11日 14点09分
回复 Nukepayload2 :看来WPF控件不是通过“Windows窗体”的方式实现的。
2013年09月12日 00点09分
level 13
Nukepayload2 楼主
自己解决了。我把代码彻底重构了一次,功能代码与窗体类分离,结果截图后约5秒,内存占用率下降了。
2013年09月11日 14点09分 11
level 5
挖一下坟。
据我分析,内存泄露主要是“Using g As Graphics”这里的g需要销毁掉。
加一句g.Dispose()会好很多。
然后之前截图生成的图片,如果不用了,也要Dispose()才行。
If Not BackgroundImage Is Nothing Then BackgroundImage.Dispose() '在修改背景图片之前,销毁旧的背景图片
System.GC.Collect() '在适当的时机和代码位置,强制进行即时垃圾回收(会增加 CPU 负荷)
2017年07月30日 12点07分 13
你这叫 “double free”。是不安全的。
2017年07月30日 13点07分
之前生成的转换成 BitmapSource 之后已经释放掉了。
2017年07月30日 13点07分
@Nukepayload2 不用Using,用正常的Dim,你可以开循环试。实测Using的不会调用Dispose()。
2017年07月30日 13点07分
回复 MoonAngie : 会调用的。要不为什么有 Using ?
2017年07月30日 13点07分
level 5
2017年07月30日 12点07分 15
level 5
然后闪烁的问题,可以这样:
SetStyle(ControlStyles.OptimizedDoubleBuffer, True) '先在缓冲区中绘制,然后再绘制到屏幕上,以减少闪烁
SetStyle(ControlStyles.AllPaintingInWmPaint, True) '忽略擦除背景的窗口消息,不擦除之前的背景,以减少闪烁
2017年07月30日 12点07分 16
WPF 不支持 SetStyle。
2017年07月30日 13点07分
闪烁只是 Winform 的 Bug。跟 WPF 没有任何关系。
2017年07月30日 13点07分
@Nukepayload2 WPF。。。好吧。。。
2017年07月30日 13点07分
level 5
截图:
Dim ScreenArea As Rectangle = My.Computer.Screen.Bounds
Dim Temp As New Bitmap(ScreenArea.Width, ScreenArea.Height)
Dim Graphics As Graphics = Graphics.FromImage(Temp)
Graphics.CopyFromScreen(0, 0, 0, 0, ScreenArea.Size)
Graphics.Dispose()
Return Temp
2017年07月30日 13点07分 17
level 5
我是这么写的截图。
开循环暴力测试,没有内存泄露的问题。
2017年07月30日 13点07分 18
这个写法跟用 Using 是等效的
2017年07月30日 13点07分
除非 CopyFromScreen 抛出异常
2017年07月30日 13点07分
@Nukepayload2 [滑稽]你这么一说好像是诶。。。
2017年07月30日 13点07分
1