C# 位图。保存,巨大的内存泄漏
我有一个应用程序,我在内存中获取位图并使用GZipStream压缩它,然后通过套接字发送。我已追踪到肮脏的人渣内存泄漏到以下线路:C# 位图。保存,巨大的内存泄漏,c#,memory-leaks,bitmap,C#,Memory Leaks,Bitmap,我有一个应用程序,我在内存中获取位图并使用GZipStream压缩它,然后通过套接字发送。我已追踪到肮脏的人渣内存泄漏到以下线路: frame.Save(inStream, jpegCodec, parameters); 浏览good ol的信息高速公路,我发现了许多关于图像类在各种编解码器的save方法中泄漏内存的主题。问题是我找不到任何解决办法。因此,我的问题如下: 这是什么原因 我怎样才能解决这个问题 下面是泄漏所在的FrameStream类中的完整Write()方法 /// <s
frame.Save(inStream, jpegCodec, parameters);
浏览good ol的信息高速公路,我发现了许多关于图像类在各种编解码器的save方法中泄漏内存的主题。问题是我找不到任何解决办法。因此,我的问题如下:
/// <summary>
/// Writes a frame to the stream
/// </summary>
/// <param name="frame">The frame to write</param>
public void Write(Bitmap frame) {
using (EncoderParameter qualityParameter = new EncoderParameter(Encoder.Quality, 50L)) {
using (EncoderParameters parameters = new EncoderParameters(1)) {
parameters.Param[0] = qualityParameter;
ImageCodecInfo[] codecs = ImageCodecInfo.GetImageEncoders();
ImageCodecInfo jpegCodec = null;
foreach (ImageCodecInfo codec in codecs) {
if (codec.MimeType == "image/jpeg") {
jpegCodec = codec;
break;
}
}
using (MemoryStream inStream = new MemoryStream()) {
frame.Save(inStream, jpegCodec, parameters); // HUUUGE Memory Leak
Byte[] buffer = new Byte[inStream.Length];
inStream.Read(buffer, 0, buffer.Length);
using (MemoryStream outStream = new MemoryStream()) {
using (GZipStream gzipStream = new GZipStream(outStream, CompressionMode.Compress)) {
gzipStream.Write(buffer, 0, buffer.Length);
}
Byte[] frameData = outStream.ToArray();
Byte[] packet = new Byte[15 + frameData.Length];
Byte[] frameLength = BitConverter.GetBytes(frameData.Length);
Array.Copy(frameLength, 0, packet, 0, frameLength.Length);
Array.Copy(frameData, 0, packet, 15, frameData.Length);
m_Socket.Send(packet);
}
}
}
}
}
//
///将帧写入流
///
///写作的框架
公共无效写入(位图帧){
使用(编码器参数质量参数=新编码器参数(编码器质量,50L)){
使用(编码器参数参数=新编码器参数(1)){
parameters.Param[0]=质量参数;
ImageCodecInfo[]codecs=ImageCodecInfo.GetImageEncoders();
ImageCodecInfo jpegCodec=null;
foreach(编解码器中的ImageCodeInfo编解码器){
如果(codec.MimeType==“图像/jpeg”){
JPEG编解码器=编解码器;
打破
}
}
使用(MemoryStream inStream=新的MemoryStream()){
frame.Save(流内、JPEG编解码器、参数);//HUUUGE内存泄漏
字节[]缓冲区=新字节[流内长度];
流内读取(缓冲区,0,缓冲区长度);
使用(MemoryStream outStream=新MemoryStream()){
使用(gzip流gzip流=新的gzip流(扩展,压缩模式.Compress)){
写入(buffer,0,buffer.Length);
}
Byte[]frameData=outStream.ToArray();
字节[]数据包=新字节[15+帧数据.Length];
Byte[]frameLength=位转换器.GetBytes(frameData.Length);
复制(frameLength,0,packet,0,frameLength.Length);
复制(frameData,0,packet,15,frameData.Length);
m_套接字发送(数据包);
}
}
}
}
}
我对套接字知之甚少。但是,我知道使用Image类阻止内存泄漏的一种方法是冻结位图。希望能为您提供更多信息。MemoryStream.Dispose会失败吗?因此,造成内存泄漏 我对插座了解不多。但是,我知道使用Image类阻止内存泄漏的一种方法是冻结位图。希望能为您提供更多信息。MemoryStream.Dispose会失败吗?因此,造成内存泄漏 是否正在调用图形对象的.Dispose()方法?这将导致内存泄漏。编辑:写入字节[]后,现在可以清除位图对象的.Dispose()。是否调用图形对象的.Dispose()方法?这将导致内存泄漏。编辑:写入字节[]后,现在可以清除位图对象的.Dispose()。处理完位图后,应将其设置为null
此外,您可能希望在处理位图后调用垃圾收集器(即使这是一个昂贵的操作):GC.Collect()代码>
位图保存非托管资源-GC并不总是对这些资源“在行”。这里有一个关于位图类的有趣链接(从compact框架的角度):处理完位图后,应该将其设置为null
此外,您可能希望在处理位图后调用垃圾收集器(即使这是一个昂贵的操作):GC.Collect()代码>
位图保存非托管资源-GC并不总是对这些资源“在行”。这里有一个关于位图类的有趣链接(从compact框架的角度):我建议在CLR Profiler下运行您的代码以查找泄漏源。如果它是任何类型的托管对象(甚至是非托管资源),只要该错误不是由于托管类型泄漏非托管句柄造成的,您就可以看到泄漏的位置。如果它在框架代码中,您可能可以使用反射和P/Invoke来解决它
例如,在某些情况下,图标
类型会泄漏Win32HICON
s。解决方法是手动处理HICON
,方法是使用图标所显示的句柄,通过PInvokingDeleteObject
函数,我建议在CLR Profiler下运行代码,以定位泄漏源。如果它是任何类型的托管对象(甚至是非托管资源),只要该错误不是由于托管类型泄漏非托管句柄造成的,您就可以看到泄漏的位置。如果它在框架代码中,您可能可以使用反射和P/Invoke来解决它
例如,在某些情况下,图标
类型会泄漏Win32HICON
s。解决方法是,在尝试了每个人的想法和想法以及许多其他方法后,使用图标
公开的手柄,通过PInvoking删除对象
功能手动处理HICON
。我终于尝试了简单的方法:
using (frame) {
frame.Save(outStream, jpegCodec, parameters);
}
好吧,这起作用了,内存泄漏得到了修复。。我尝试强制调用垃圾收集器,手动处理位图,使用P/Invoke DeleteObject,但没有任何效果,但使用using语句就成功了。因此,这让我想知道,在尝试了每个人的想法和想法之后,在一个我错过的使用语句下会发生什么