Windows服务中的计时器和异常处理

时间:2011-10-11 12:08:00

标签: c# windows-services

我在下面提到的代码中遇到了奇怪的问题。我不明白究竟是什么问题。下面的代码是Windows服务的一部分。此代码调用一个com类函数,在固定间隔后对消息队列执行某些操作。 为此,我使用了System.threading.timer。启动后,服务工作正常一段时间,但一段时间后它停止工作。

using System;
using System.IO;
using System.ServiceProcess;
using System.Threading;
using CareMC.VBWrapper.RCWQueue;

namespace MSPQueueService
{
    public partial class MSPQueueService : ServiceBase
    {
        static System.Threading.Timer timer;
        const int TIMEOUTVALUE = 5000;
        private int isBusy = 0;
        public MSPQueueService()
        {
            InitializeComponent();
        }

        protected override void OnStart(string[] args)
        {
            try
            {
                AppendToLog("ONStart Begin");
                //Handle Elapsed event

                TimerCallback timerDelegate = new TimerCallback(OnElapsedTime);

                timer = new System.Threading.Timer(timerDelegate, null, TIMEOUTVALUE, TIMEOUTVALUE);
                //EVENT _objEvent = new EVENT();
                //_objEvent.ExecuteMSPQueue();
                AppendToLog("ONStart End");
            }
            catch (Exception ex)
            {
                string ErrorMessage = ex.Message.ToString();
                AppendToLog(ErrorMessage);
            }

        }

        private void OnElapsedTime(object state)
        {

            //If the isBusy value is 0 then replace it with 1 and continue otherwise it has already been incremented so we're already running

            //the handler so skip out

            if (Interlocked.CompareExchange(ref isBusy, 1, 0) != 0)
            {
                AppendToLog("OnElapsedTime is already running. isBusy=" + isBusy.ToString());
                return;
            }

            try
            {

                EVENT _objEvent = new EVENT();
                AppendToLog("Before Executing ExecuteMSPQueue function.");
                _objEvent.ExecuteMSPQueue();
                AppendToLog("After Executing ExecuteMSPQueue function.");
            }
            catch (Exception ex)
            {
                AppendToLog(ex.ToString());
            }
            finally
            {
                AppendToLog("Resetting  isBusy value to 0=");
                Interlocked.Exchange(ref isBusy, 0);
                AppendToLog("Value of   isBusy  after reset =" + isBusy);

            };

        }


}

这是代码

中的smaple日志
  

10/11/2011 4:15:03 AM:执行ExecuteMSPQueue函数之前。

     

10/11/2011 4:15:08 AM:OnElapsedTime已经在运行。

     

10/11/2011 4:15:13 AM:OnElapsedTime已经在运行。

     

10/11/2011 4:15:18 AM:OnElapsedTime已经在运行。

     

10/11/2011 4:15:19 AM:执行ExecuteMSPQueue函数后。

     

10/11/2011 4:15:28 AM:OnElapsedTime已经在运行。

     

10/11/2011 4:15:33 AM:OnElapsedTime已经在运行。

     

10/11/2011 4:15:38 AM:OnElapsedTime已经在运行。

     

10/11/2011 4:15:43 AM:OnElapsedTime已经在运行。

     

10/11/2011 4:15:48 AM:OnElapsedTime已经在运行。

     

10/11/2011 4:15:53 AM:OnElapsedTime已经在运行。

这意味着IsBusy变量的值保持为1且不重置为0。通过查看代码,只有在catch块中没有被捕获的异常才有可能。(这可能吗?)

请帮帮我。

2 个答案:

答案 0 :(得分:1)

无论前一次运行是否结束,计时器都会触发。如果OnElapsedTime运行时间超过5秒,则当计时器再次执行时,该值仍为1。

从线程池线程调用回调委托,因此可以使用这种特定情况。

来自MSDN:

  

为回调指定的方法应该是可重入的,因为它是   调用ThreadPool线程。该方法可以执行   如果定时器间隔是,则同时在两个线程池线程上   少于执行该方法所需的时间,或者所有线程   池线程正在使用中,并且该方法已多次排队。

编辑:

根据评论,鉴于你的 finally 块永远不会运行,我猜你记录“After Executing”的线程仍然挂起或死锁,无论是在日志记录方法上,或者可能是EVENT的终结者(如果有的话)。这是通过调试器逐步完成可能非常有启发性的地方。

答案 1 :(得分:0)

请注意您的日志记录方法,您可能会遇到可能导致您遇到问题的并发问题。根据您的要求,我将使用Thread + Thread.Sleep()重新设计您的服务。