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块中没有捕获异常的情况下才有可能。(这可能吗?)
请帮帮我。
无论前一次运行是否完成,计时器都会触发。如果OnElapsedTime运行时间超过5秒,当计时器再次执行时,该值仍然为1。
回调委托是从线程池线程调用的,所以这种特殊情况是可能的。
从MSDN:编辑:为callback指定的方法应该是可重入的,因为它是在ThreadPool线程上调用。可以执行该方法同时在两个线程池线程上运行,如果定时器间隔为少于执行该方法所需的时间,如果是所有线程池线程正在使用中,并且该方法已多次排队。
根据评论,考虑到你的finally块从未运行,我猜你的记录"执行后"的线程仍然挂起或死锁,要么在日志方法上,要么可能是EVENT的终结器(如果它有一个)。在这里,使用调试器可能会非常有启发。
小心你的日志记录方法,你可能有并发的问题,这可能会导致你遇到的问题。根据您的需求,我会使用Thread + Thread. sleep()来重新设计您的服务。