C#中的内存管理用于高速应用程序

时间:2014-06-25 17:27:29

标签: c# memory

我正在构建一个应用程序,它处理来自文件或缓冲区的传入图像,并以数组或固定大小的双精度形式输出结果。应用程序需要相对较快。我遇到了循环时间问题。我开始记录循环时间,同时处理一个图像,它从最小值65毫秒开始逐渐增加到500毫秒,这太慢了。果然,我检查了内存使用量,并且它也在稳步增加。

我在每个周期后运行GC并尽可能地转储未使用的变量。我没有在处理循环中创建新对象。图像处理在其自己的线程上完成,以便所有资源都被转储。当我从文件中提取图像时,似乎大部分周期时间都会增加。我能错过什么?

这里是粗略的代码,完整的东西非常大。主要功能

         private void button4_Click(object sender, EventArgs e)
    {
        Stopwatch sw = new Stopwatch();
        sw.Start();

        cogDisplay1.Image = null; 
        ImageFromFile.Operator.Open(Properties.Settings.Default.ImageFile, CogImageFileModeConstants.Read);
        ImageFromFile.Run();

        cogDisplay1.Image = ImageFromFile.OutputImage;
        cogDisplay1.AutoFit = true;
        Thread t = new Thread(Vision);
        t.Start();
        textBox3.Clear();
        sw.Stop();
        textBox3.AppendText(sw.ElapsedMilliseconds.ToString() + Environment.NewLine + "TS: " + t.ThreadState.ToString());
        textBox3.AppendText("GC" + GC.GetTotalMemory(true).ToString());
        GC.Collect(GC.MaxGeneration , GCCollectionMode.Forced, false);

    }

图像处理

 public void Vision()
    {
        Stopwatch sw = new Stopwatch();
        sw.Start();

        try
        {

            AlignmentParams.ApproximateNumberToFind = 1;
            AlignmentParams.SearchRegionMode = 0;


            AlignmentResult = AlignmentPat.Execute(cogDisplay1.Image as CogImage8Grey, null , AlignmentParams);
            Fixture.InputImage = cogDisplay1.Image;
            Fixture.RunParams.UnfixturedFromFixturedTransform = AlignmentResult[0].GetPose();
            Fixture.Run();
            AlignmentResult = null;


        #region FindLineTools 
        #endregion 
        #region FindEllipse 
        #endregion 


                sw.Stop();
                SetText("V" + sw.ElapsedMilliseconds.ToString() + Environment.NewLine);




        }
        catch (Exception err) 
        {

           SetText(Environment.NewLine + "***********Error***********" + Environment.NewLine);
           SetText(err.ToString() + Environment.NewLine);
           SetText("***************************" + Environment.NewLine);
        }




    }

2 个答案:

答案 0 :(得分:0)

首先,我建议发布一个清理过的代码以提高可读性(删除所有注释掉的东西)。其次,只关注重要部分,即:你的问题是由于图像处理繁重导致的内存过度使用/泄漏(如果错误则更正)。因此,在名为Vision的线程中,取消引用图像对象并在处理完成后立即将它们设置为null(如上所述,GC在您的情况下不是很大的帮助)。下面的代码片段简要说明了这个概念:

    public void Vision()
        {
            Stopwatch sw = new Stopwatch();
            sw.Start();

            try
            {

                AlignmentParams.ApproximateNumberToFind = 1;
                AlignmentParams.SearchRegionMode = 0;
                    AlignmentResult = AlignmentPat.Execute(cogDisplay1.Image as CogImage8Grey, null , AlignmentParams);
                Fixture.InputImage = cogDisplay1.Image;
                Fixture.RunParams.UnfixturedFromFixturedTransform = AlignmentResult[0].GetPose();
                Fixture.Run();
                AlignmentResult = null;

            // your coding stuff

                    sw.Stop();
                    SetText("V" + sw.ElapsedMilliseconds.ToString() + Environment.NewLine);

            }
            catch (Exception err) 
            {

               SetText(Environment.NewLine + "***********Error***********" + Environment.NewLine);
               SetText(err.ToString() + Environment.NewLine);
               SetText("***************************" + Environment.NewLine);
            }
finally{Fixture.InputImage=null}

答案 1 :(得分:0)

不要打电话给GC.Collect。让VM决定何时内存不足并且必须进行收集。您通常无法确定GC.Collect的最佳时间,除非您运行其他心跳或空闲观看线程。

其次,确保您从方法调用接收的任何资源都是Disposed。将变量设置为NULL不会这样做,您应该显式调用Dispose或在Using block:

using(SomeResource resource = Class.GiveMeResource("image.png"))
{
   int width = resource.Width;
   int height = resource.Height;
   Console.Write("that image has {0} pixels", width*height);
} //implicitly calls IDisposable.Dispose() here.

您还需要做一些内存并调用分析来检测存在泄漏的位置。