Aforge.Video MJPEGStream磁盘占用过高,是否存在资源泄漏?
我来帮你分析下这个问题——你的代码确实存在资源泄漏的风险,这大概率就是C盘空间持续被占用的根源,具体拆解来看:
问题代码回顾
你用来初始化MJPEG流的代码:
MJPEGStream stream = new MJPEGStream("http://192.168.88.252/cgi-bin/mjpeg?resolution=1920x1080&quality=1&page=1517608886020&Language=0"); stream.NewFrame += Stream_NewFrame; stream.Start();
以及帧处理的事件方法:
private void Stream_NewFrame(object sender, NewFrameEventArgs eventArgs) { try { Bitmap bitmap = eventArgs.Frame.Clone() as Bitmap; pictureBox1.Image = bitmap; } catch (Exception e) { } }
核心问题分析
未释放旧的Image资源
每次给pictureBox1.Image赋值新Bitmap时,原来的Image对象完全没被手动释放。GDI+的Bitmap属于非托管资源,.NET垃圾回收器不会主动及时回收这类资源,长期积累下来会导致大量闲置的GDI资源堆积,迫使系统扩大分页文件(虚拟内存),直接表现为C盘空间被持续占用。空异常捕获掩盖问题
你用了catch (Exception e) { }空捕获逻辑,这会把资源释放过程中可能出现的错误(比如Dispose失败、帧克隆异常等)完全掩盖,让你无法及时定位潜在的泄漏点。流资源未主动清理(潜在风险)
如果程序没有在停止流时调用stream.Stop()和stream.Dispose(),MJPEGStream内部可能残留未释放的网络连接、缓存资源,进一步加剧资源占用问题。
修复方案
1. 处理帧时主动释放旧Image资源
修改Stream_NewFrame方法,在设置新Bitmap前先清理旧的Image:
private void Stream_NewFrame(object sender, NewFrameEventArgs eventArgs) { try { // 用using块确保克隆的临时帧被正确释放 using (Bitmap clonedFrame = eventArgs.Frame.Clone() as Bitmap) { if (clonedFrame == null) return; // 先释放PictureBox的旧Image资源 if (pictureBox1.Image != null) { pictureBox1.Image.Dispose(); } // 将克隆后的帧赋值给PictureBox pictureBox1.Image = new Bitmap(clonedFrame); } } catch (Exception e) { // 不要空捕获,至少记录异常信息方便排查 Debug.WriteLine($"帧处理出错: {e.Message}\n{e.StackTrace}"); } }
2. 程序退出/停止流时清理所有资源
在窗体关闭或停止流的逻辑中,确保彻底释放流和PictureBox的资源:
private void Form_FormClosing(object sender, FormClosingEventArgs e) { // 清理MJPEGStream资源 if (stream != null) { stream.NewFrame -= Stream_NewFrame; stream.Stop(); stream.Dispose(); stream = null; } // 清理PictureBox的Image资源 if (pictureBox1.Image != null) { pictureBox1.Image.Dispose(); pictureBox1.Image = null; } }
3. 检查库的缓存配置
如果你的MJPEGStream来自AForge.NET这类第三方库,建议查看是否有磁盘缓存相关配置项,确保缓存可以自动清理或设置合理的缓存大小,避免缓存文件占用过多磁盘空间。
总结
你的代码存在明确的资源泄漏风险,主要是未正确释放GDI资源导致的虚拟内存膨胀。按照上述方案修改后,应该能有效解决C盘空间持续被占用的问题。
内容的提问来源于stack exchange,提问作者mackai911

