内存泄漏C#app?怎么停?

时间:2014-02-10 06:49:02

标签: c# memory-leaks

我的应用 巨大的内存泄漏 ,内存使用率在运行1天后 40MB到700MB 。我用C#编码,我不知道如何阻止泄漏。我怀疑下面2个功能是罪魁祸首。

SendLiveVideo :它从相机捕获并通过套接字发送 ResizeImage :为了节省带宽,它会在我通过套接字发送之前调整图像大小。

我的应用程序调用第三方库( LibImage,Libcapture)从旧网络摄像头(4个摄像头)捕获图像,并作为视频流传输到LAN连接客户端列表。

我已经在退出Sendvideo函数时在finally语句中为我的*变量分配了 null 值以释放内存,但它似乎无法正常工作。

我是否需要使用Dispose方法?

this.timer_stream0.Interval = 30; /*I capture image and send to client this every 30 milseconds make it as video stream to human eye*/
this.timer_stream0.Tick += new System.EventHandler(this.timer_stream0_Tick);
private void timer_stream0_Tick(object sender, EventArgs e)
{
            ThreadPool.QueueUserWorkItem(SendLiveVideo, 0);
            ThreadPool.QueueUserWorkItem(SendLiveVideo, 1);
            ThreadPool.QueueUserWorkItem(SendLiveVideo, 2);
            ThreadPool.QueueUserWorkItem(SendLiveVideo, 3);
}
void SendLiveVideo(object state)
{
    LibImage image=new LibImage();
    LibCapture capture_camera=new LibCapture();
    int cam = (int)state;
System.Collections.ArrayList m_workerSocketList_Video =
ArrayList.Synchronized(new System.Collections.ArrayList());

    switch (cam)
    {
        case 0:
            {
                image = image0;
                capture_camera = capture_camera0;
                m_workerSocketList_Video = m_workerSocketList_Video0;
                break;
            }
        case 1:
            {
                image = image1;
                capture_camera = capture_camera1;
                m_workerSocketList_Video = m_workerSocketList_Video1;
                break;
            }
        case 2:
            {
                image = image2;
                capture_camera = capture_camera2;
                m_workerSocketList_Video = m_workerSocketList_Video2;
                break;
            }
        default:
            {
                image = image3;
                capture_camera = capture_camera3;
                m_workerSocketList_Video = m_workerSocketList_Video3;
                break;
            }
    }


    byte[] imageData=new byte[1000 * 1000 * 10];
    try
    {

        try
        {
            capture_camera.Capture(image);
        }
        catch
        {
            // objData = null;
            imageData = null;
            return;
        }

        imageData = image.SaveToMem(PNG);
        var stream = new MemoryStream(imageData);
        {
            var bitmap = new Bitmap(stream);
            bitmap = ResizeImage(bitmap, new Size(150, 112));
            //stream = null;
            MemoryStream streamnew = new MemoryStream();
            bitmap.Save(streamnew, ImageFormat.Png);
            imageData = streamnew.ToArray();
            bitmap = null;
            streamnew = null;
        }
        Socket workerSocket = null;
        for (int i = 0; i < m_workerSocketList_Video.Count; i++)
        {
            workerSocket = (Socket)m_workerSocketList_Video[i];
            if (workerSocket != null)
            {
                if (SocketConnected(workerSocket)) 
                {
                    workerSocket.Send(imageData);
                }
            }
        }


    }
    catch (SocketException se)
    {
        // MessageBox.Show(se.Message);
        return;
    }

    finally
    {
        image = null;
        capture_camera = null;
        imageData = null;
        m_workerSocketList_Video = null;
    }
}
private Bitmap ResizeImage(Bitmap imgToResize, Size size)
    {
        try
        {
            int sourceWidth = imgToResize.Width;
            int sourceHeight = imgToResize.Height;
        float nPercent = 0;
        float nPercentW = 0;
        float nPercentH = 0;

        nPercentW = ((float)size.Width / (float)sourceWidth);
        nPercentH = ((float)size.Height / (float)sourceHeight);

        if (nPercentH < nPercentW)
            nPercent = nPercentH;
        else
            nPercent = nPercentW;

        int destWidth = (int)(sourceWidth * nPercent);
        int destHeight = (int)(sourceHeight * nPercent);

        Bitmap b = new Bitmap(destWidth, destHeight, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
        b.SetResolution(200, 200);
        Graphics g = Graphics.FromImage((Image)b);
        g.InterpolationMode = InterpolationMode.HighQualityBicubic;
        g.CompositingQuality = CompositingQuality.HighSpeed;
        g.SmoothingMode = SmoothingMode.HighSpeed;

        g.DrawImage(imgToResize, 0, 0, destWidth, destHeight);
        g.Dispose();

        return b;
    }

3 个答案:

答案 0 :(得分:1)

试着看看我的回答here

基本上,这是一种如何找到泄漏原点的方法 这实际上是一个复制粘贴:

  1. 打开内存探查器。我使用perfmonThis文章提供了一些关于设置perfmon的内容,@fmunkert也很好地解释了它。
  2. 在代码中找到您怀疑泄漏可能位于该区域的区域。这部分主要取决于您对代码中负责该问题的部分有很好的猜测。
  3. 将泄漏推至极端:使用标签和“goto”隔离区域/功能并多次重复可疑代码(循环将起作用。我发现goto更方便了物质)。
  4. 在循环中,我使用了断点,每50次命中停止一次,以检查内存使用量的增量。当然,您可以将值更改为应用程序中明显的泄漏更改。
  5. 如果找到导致泄漏的区域,则内存使用量应迅速增加。如果内存使用量没有增加,请使用您怀疑是根本原因的另一个代码区域重复1-4阶段。如果是,请继续6。
  6. 在您发现原因的区域,使用相同的技术(转到+标签)放大并隔离区域的较小部分,直到找到泄漏源(请不要为了递归而向我投票)步......:0))。
  7. 请注意,此方法的缺点是:

    1. 如果你在循环中分配一个对象,它的处理也应该包含在循环中。
    2. 如果你有多个泄漏源,那就更难发现(但仍然可能)

答案 1 :(得分:0)

我会用

        using(Graphics g = Graphics.FromImage((Image)b))
        {
             g.InterpolationMode = InterpolationMode.HighQualityBicubic;
             g.CompositingQuality = CompositingQuality.HighSpeed;
             g.SmoothingMode = SmoothingMode.HighSpeed;

             g.DrawImage(imgToResize, 0, 0, destWidth, destHeight);
        }

        return b;
实现IDisposable的每种类型的

模式,这样你就不会忘记处理任何东西了吗?

答案 2 :(得分:0)

  • 每当使用IDisposable实例时,您都必须使用using关键字。

    使用(MemoryStream streamnew = new MemoryStream())   //你的位图实例也一样!

  • 如果是这种情况,你必须检查LibImage和LibCapture的实现以及它们包装的本机库。

  • 没有必要实例化所有这三个变量image,capture_camera和m_workerSocketList_Video,因为你要在switch语句中初始化它们,除非。如果这些类是库的本机包装器,那么这将导致显着的内存丢失,这些库很难管理它们使用的内存。

  • 使用这行代码,

    imageData = image.SaveToMem(PNG);

如果SaveToMem函数返回正确的缓冲区,则不需要启动imageData数组!