我正在构建一个应用程序,它处理来自文件或缓冲区的传入图像,并以数组或固定大小的双精度形式输出结果。应用程序需要相对较快。我遇到了循环时间问题。我开始记录循环时间,同时处理一个图像,它从最小值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);
}
}
答案 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.
您还需要做一些内存并调用分析来检测存在泄漏的位置。