Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/331.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 位图。保存,巨大的内存泄漏_C#_Memory Leaks_Bitmap - Fatal编程技术网

C# 位图。保存,巨大的内存泄漏

C# 位图。保存,巨大的内存泄漏,c#,memory-leaks,bitmap,C#,Memory Leaks,Bitmap,我有一个应用程序,我在内存中获取位图并使用GZipStream压缩它,然后通过套接字发送。我已追踪到肮脏的人渣内存泄漏到以下线路: frame.Save(inStream, jpegCodec, parameters); 浏览good ol的信息高速公路,我发现了许多关于图像类在各种编解码器的save方法中泄漏内存的主题。问题是我找不到任何解决办法。因此,我的问题如下: 这是什么原因 我怎样才能解决这个问题 下面是泄漏所在的FrameStream类中的完整Write()方法 /// <s

我有一个应用程序,我在内存中获取位图并使用GZipStream压缩它,然后通过套接字发送。我已追踪到肮脏的人渣内存泄漏到以下线路:

frame.Save(inStream, jpegCodec, parameters);
浏览good ol的信息高速公路,我发现了许多关于图像类在各种编解码器的save方法中泄漏内存的主题。问题是我找不到任何解决办法。因此,我的问题如下:

  • 这是什么原因
  • 我怎样才能解决这个问题
  • 下面是泄漏所在的FrameStream类中的完整Write()方法

    /// <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来解决它


    例如,在某些情况下,
    图标
    类型会泄漏Win32
    HICON
    s。解决方法是手动处理
    HICON
    ,方法是使用
    图标所显示的句柄,通过PInvoking
    DeleteObject
    函数,我建议在CLR Profiler下运行代码,以定位泄漏源。如果它是任何类型的托管对象(甚至是非托管资源),只要该错误不是由于托管类型泄漏非托管句柄造成的,您就可以看到泄漏的位置。如果它在框架代码中,您可能可以使用反射和P/Invoke来解决它


    例如,在某些情况下,
    图标
    类型会泄漏Win32
    HICON
    s。解决方法是,在尝试了每个人的想法和想法以及许多其他方法后,使用
    图标
    公开的手柄,通过PInvoking
    删除对象
    功能手动处理
    HICON
    。我终于尝试了简单的方法:

    using (frame) {
        frame.Save(outStream, jpegCodec, parameters);
    }
    

    好吧,这起作用了,内存泄漏得到了修复。。我尝试强制调用垃圾收集器,手动处理位图,使用P/Invoke DeleteObject,但没有任何效果,但使用using语句就成功了。因此,这让我想知道,在尝试了每个人的想法和想法之后,在一个我错过的使用语句下会发生什么