情况就是这样:
一家企业有几个网站,每个网站都有几个摄像头,每天拍摄照片(每张约一千张照片)。然后将这些图片存储在一台计算机上的文件夹(一天中的一个文件夹)中。
该企业拥有一个图像分析程序,该程序获取“in.xml”文件作为输入并返回“out.xml”文件,用于分析一张图片。该程序必须使用,不能更改。 我为该程序编写了一个UI,该程序在该文件夹上运行并处理每个站点的每个摄像头,将pic后的pic发送到该程序,该程序作为一个单独的进程运行。 由于此处理是异步的,因此我在每张图片处理的开始和结束时都使用了事件,而网站上的网站和摄像头也是如此。
该程序在该业务上运行很大,但有时它在处理pic之后就会卡住,就像它已经错过了end_pic_analizing事件,并且仍在等待它被抛出。 我尝试为每张照片设置一个计时器,在这种情况下移动到下一张照片,但它仍然再次卡住,表现得像是错过了计时器事件。
这个错误发生的次数太多了,即使在该计算机上几乎像单个进程一样运行,并且即使在进程开始时也会卡住(发生在第三张图片一次)。这个bug也不依赖于特定的图片,因为它可以卡在不同的图片上,或者根本不会卡在同一个文件夹上。
代码示例: 在Image类:
static public void image_timer_Elapsed(object sender, ElapsedEventArgs e)
{
//stop timer and calculate the how much time left for next check for file.
_timer.Stop();
_timerCount += (int)_timer.Interval;
int timerSpan = (int)(Daily.duration * 1000) - _timerCount;
//daily.duration is the max duration for seekin the "out.xml" file before quiting.
if (timerSpan < _timer.Interval) _timer.Interval = timerSpan + 1;
//check for file and analize it.
String fileName = Daily.OutPath + @"\out.xml";
ResultHandler.ResultOut output = ResultHandler.GetResult(ref _currentImage);
//if no file found and there is time left wait and check again
if (output == ResultHandler.ResultOut.FileNotFound && timerSpan > 0)
{
_timer.Start();
}
else //file found or time left
{
if (MyImage.ImageCheckCompleted != null)
MyImage.ImageCheckCompleted(_currentImage); //throw event
// the program is probably got stuck here.
}
在相机课上:
static public void Camera_ImageCheckCompleted(MyImage image)
{
//if this is not the last image. (parent as Camera )
if (image.Id + 1 < image.parent.imageList.Count)
{
image.parent.imageList[image.Id + 1].RunCheck(); //check next image
}
else
{
if (Camera.CameraCheckCompleted != null)
Camera.CameraCheckCompleted(image.parent); // throw event
}
}
答案 0 :(得分:1)
您似乎没有任何错误处理或记录代码,因此如果抛出异常,您的程序将停止,并且您可能没有记录发生的情况。这是特别正确的,因为您的程序是异步处理图像,因此主线程可能已经在您的一个处理线程中发生错误时退出。
首先,我建议在所有在单独线程中运行的代码周围抛出一个try/catch
块。如果在那里抛出异常,您将需要捕获该异常并使用一些特殊事件参数触发ImageCheckCompleted
以指示存在错误或触发您在发生错误时专门创建的其他事件。这样,即使在代码中抛出异常,您的程序也可以继续处理。
try
{
//... Do your processing
// This will happen if everything worked correctly.
InvokeImageCheckCompleted(new ImageCheckCompletedEventArgs();
}
catch (Exception e)
{
// This will happen if an exception got thrown.
InvokeImageCheckCompleted(new ImageCheckCompletedEventArgs(e);
}
为简单起见,我建议使用for
循环来处理每个图像。您可以使用ManualResetEvent
阻止执行,直到每个检查触发ImageCheckCompleted
事件为止。这应该可以更容易地记录每个循环的执行,捕获可能阻止ImageCheckCompleted
事件触发的错误,甚至可能继续处理下一个图像,如果其中一个看起来花费的时间太长。
最后,如果您可以使图像处理成为线程安全的,您可以考虑使用Parallel.ForEach
进行处理,以便可以同时处理多个图像。这可能会显着提高处理批次的整体速度。