windows服务中的定时器和异常处理

本文关键字:异常处理 定时器 服务 windows | 更新日期: 2023-09-27 18:11:09

我对下面提到的代码有奇怪的问题。我不明白到底是什么问题。下面的代码是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);
            };
        }

}

下面是来自代码

的示例日志

10/11/2011 4:15:03 AM: Before execute ExecuteMSPQueue函数。

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

10/11/2011 4:15:13 AM: OnElapsedTime is already running.

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

10/11/2011 4:15:19 AM: After execute 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块中没有捕获异常的情况下才有可能。(这可能吗?)

请帮帮我。

windows服务中的定时器和异常处理

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

回调委托是从线程池线程调用的,所以这种特殊情况是可能的。

从MSDN:

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

编辑:

根据评论,考虑到你的finally块从未运行,我猜你的记录"执行后"的线程仍然挂起或死锁,要么在日志方法上,要么可能是EVENT的终结器(如果它有一个)。在这里,使用调试器可能会非常有启发。

小心你的日志记录方法,你可能有并发的问题,这可能会导致你遇到的问题。根据您的需求,我会使用Thread + Thread. sleep()来重新设计您的服务。