程序因丢失抛出的事件而停滞不前

时间:2011-09-03 21:05:07

标签: c# events event-handling

情况就是这样:

一家企业有几个网站,每个网站都有几个摄像头,每天拍摄照片(每张约一千张照片)。然后将这些图片存储在一台计算机上的文件夹(一天中的一个文件夹)中。

该企业拥有一个图像分析程序,该程序获取“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
        }
    }

1 个答案:

答案 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进行处理,以便可以同时处理多个图像。这可能会显着提高处理批次的整体速度。