程序不会停止堆叠内存

时间:2014-02-04 11:13:30

标签: c# garbage-collection out-of-memory

我写了一个程序,显示来自传感器的实时图像。问题在于它不断消耗记忆。

        void tmr_Tick(object sender, EventArgs e)
        {
            object bpic = cam.GrabFrame();
            uint[] pic = cam.ColorPipe(bpic, out width, out height, out bitdepth);
            byte[] header = GetHeader.BuildHeader(width, height, bitdepth);
            byte[] img = GetHeader.UintImageToByte(pic, width, height, bitdepth);
            MemoryStream ms = new MemoryStream();
            GC.Collect();
            ms.Write(header, 0, header.Length);
            ms.Write(img, 0, img.Length);
            pictureBox1.Image.Dispose();
            pictureBox1.Image = Image.FromStream(ms);
            ms.Flush();
            ms.Dispose();
        }
    }
    class GetHeader
    {
        #region Image
        public static byte[] UintImageToByte(uint[] img, uint nWidth, uint nHeight, uint nBitsPerPixel)
        {
            int nBytesPerPixel = (int)nBitsPerPixel / 8;
            byte[] AoB = new byte[nWidth * nHeight * nBytesPerPixel];
            int j = 0;
            byte[] pixel;
            // Get each uint value from image and convert it to bytes
            for (int i = 0; i < img.Length; i++)
            {
                pixel = BitConverter.GetBytes(img[i]);
                // Add each pixel bytes to the image array
                for (int k = nBytesPerPixel - 1; k >= 0; k--)
                {
                    AoB[j++] = pixel[k];
                }
            }
            byte temp;
            // Swap the elements to create a true color image
            for (int i = 0; i < AoB.Length / 2; i++)
            {
                temp = AoB[i];
                AoB[i] = AoB[AoB.Length - 1 - i];
                AoB[AoB.Length - 1 - i] = temp;
            }
            return AoB;
        }
        #endregion
        #region Header
        /* IMPORTANT!!!!!
         * All numerical values are little endian!
         * 4660 in decimal will be 3421 in hex not 1234!
         * IMPORTANT!!!!! */
        private const uint HEADER_SIZE = 54;
        private const string FOUR_BYTE_ZERO = "00000000";
        private const string TWO_BYTE_ZERO = "0000";
        private const string BM = "424D";
        public static byte[] BuildHeader(uint nWidth, uint nHeight, uint nBitsPerPixel)
        {
            // Substring is to get the amount of bytes needed.
            // BitConverter currently returns 4 bytes and in case it will change
            // the substring will take the amount of bytes it needs.
            string sWidth = BitConverter.ToString(BitConverter.GetBytes(nWidth)).Replace("-", "").Substring(0, 8);
            string sHeight = BitConverter.ToString(BitConverter.GetBytes(nHeight)).Replace("-", "").Substring(0, 8);
            string sBitsPerPixel = BitConverter.ToString(BitConverter.GetBytes(nBitsPerPixel)).Replace("-", "").Substring(0, 4);
            uint nImageSize = ((nWidth * nHeight) * (nBitsPerPixel / 8));
            string sFileSize = BitConverter.ToString(BitConverter.GetBytes(nImageSize + HEADER_SIZE)).Replace("-", "").Substring(0, 8);
            string sImageSize = BitConverter.ToString(BitConverter.GetBytes(nImageSize)).Replace("-", "").Substring(0, 8);
            string sHeader = String.Empty;

            sHeader += BM;              // 0h  | File tpye          | 2 bytes
            sHeader += sFileSize;       // 2h  | File size          | 4 bytes
            sHeader += TWO_BYTE_ZERO;   // 6h  | N/A                | 2 bytes
            sHeader += TWO_BYTE_ZERO;   // 8h  | N/A                | 2 bytes
            sHeader += "36000000";      // Ah  | Data offset        | 4 bytes
            sHeader += "28000000";      // Eh  | DIB Size           | 4 bytes
            sHeader += sWidth;          // 12h | Width              | 4 bytes
            sHeader += sHeight;         // 16h | Height             | 4 bytes
            sHeader += "0100";          // 1Ah | Color planes       | 2 bytes
            sHeader += sBitsPerPixel;   // 1Ch | Bits per pixel     | 2 bytes
            sHeader += FOUR_BYTE_ZERO;  // 1Eh | Compression        | 4 bytes
            sHeader += sImageSize;      // 22h | Image size         | 4 bytes
            sHeader += FOUR_BYTE_ZERO;  // 26h | Horizontal res     | 4 bytes
            sHeader += FOUR_BYTE_ZERO;  // 2Ah | Vertical res       | 4 bytes
            sHeader += FOUR_BYTE_ZERO;  // 2Eh | Color pallete      | 4 bytes
            sHeader += FOUR_BYTE_ZERO;  // 32h | Important colors   | 4 bytes

            byte[] Header = StringToAoB(sHeader);

            return Header;
        }
        private static byte[] StringToAoB(string str)
        {
            byte[] AoB = new byte[str.Length / 2];
            for (int i = 0, j = 0; i < AoB.Length; i++, j += 2)
            {
                AoB[i] = byte.Parse(HexToInt("0x" + str[j] + str[j + 1]).ToString());
            }
            return AoB;
        }
        private static int HexToInt(string Hex)
        {
            Hex = Hex.Replace("0x", "");
            return Int32.Parse(Hex, System.Globalization.NumberStyles.AllowHexSpecifier);
        }
        #endregion

关键功能是tmr_TickUintImageToBytecam.GrabFrame()返回包含原始图像数据的单维数组。 cam.ColorPipe()将其排列为包含单维数组中每个像素的uint表示。

我不知道问题似乎在哪里,如果它的内存没有从内存流中清除,或者间隔太快(200毫秒),gc可以标记未使用的内存并清理它。 / p>

如果有人花一些时间查看代码并就如何修复代码提出一些指示,我将不胜感激。 我试过using (MemoryStream ms....)阻止无济于事。 ms.Flush()ms.Dispose()GC.Collect()试图摆脱使用过的内存,但仍然没有。

0 个答案:

没有答案