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

用于高速应用程序的C#内存管理,c#,memory,C#,Memory,我正在构建一个应用程序,该应用程序处理来自文件或缓冲区的传入图像,并以数组或固定大小的双倍形式输出结果。应用程序需要相对快速。我遇到了循环时间的问题。我在处理一幅图像时开始记录循环时间,它从最小的65毫秒开始逐渐增加到500毫秒,这太慢了。果不其然,我检查了内存使用情况,它也在稳步增长 我在每个循环后运行GC,并尽可能多地转储未使用的变量。我不会在处理循环中创建新对象。图像处理是在自己的线程上完成的,因此所有资源都会被转储。似乎大多数循环时间的增加发生在我从文件中提取图像时。我会错过什么 这是粗

我正在构建一个应用程序,该应用程序处理来自文件或缓冲区的传入图像,并以数组或固定大小的双倍形式输出结果。应用程序需要相对快速。我遇到了循环时间的问题。我在处理一幅图像时开始记录循环时间,它从最小的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);
        }




    }

首先,我建议发布一个经过清理的代码,以提高可读性(删除所有已注释的内容)。第二,只关注关键部分,即:您的问题是由于繁重的图像处理而导致的内存过度使用/泄漏(如果错误则纠正)。因此,在名为
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}

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

其次,确保从方法调用接收到的任何资源都被释放。如果不将变量设置为NULL,则应显式调用Dispose或在Using块中调用:

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.

您还需要进行一些内存和调用分析,以检测哪里存在泄漏(如果有)。

您缺少本文中的代码;)
GC.Collect
不是魔杖。它不会从仍然被引用的堆栈中收集资源。它不收集非托管内存。最后,如果您让处理器非常繁忙,GC可能无法在再次休眠之前清除那么多资源。代码对于决定哪些(如果其中任何一个)有助于您丢失内存探查器诊断非常重要,该诊断会告诉您应用程序泄漏的原因。GC.Collect完全不起任何作用。这相当于对着电脑喊“收集”。如果有任何影响的话,它只会损害性能。“在自己的线程上完成,以便转储所有资源”这根本不能保证。您需要一个AppDomain。你声称这让我想知道你的实际资源处理。