我在下面提到的代码中遇到了奇怪的问题。我不明白究竟是什么问题。下面的代码是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块中没有被捕获的异常才有可能。(这可能吗?)
请帮帮我。
答案 0 :(得分:1)
无论前一次运行是否结束,计时器都会触发。如果OnElapsedTime运行时间超过5秒,则当计时器再次执行时,该值仍为1。
从线程池线程调用回调委托,因此可以使用这种特定情况。
来自MSDN:
为回调指定的方法应该是可重入的,因为它是 调用ThreadPool线程。该方法可以执行 如果定时器间隔是,则同时在两个线程池线程上 少于执行该方法所需的时间,或者所有线程 池线程正在使用中,并且该方法已多次排队。
编辑:
根据评论,鉴于你的 finally 块永远不会运行,我猜你记录“After Executing”的线程仍然挂起或死锁,无论是在日志记录方法上,或者可能是EVENT的终结者(如果有的话)。这是通过调试器逐步完成可能非常有启发性的地方。
答案 1 :(得分:0)
请注意您的日志记录方法,您可能会遇到可能导致您遇到问题的并发问题。根据您的要求,我将使用Thread + Thread.Sleep()重新设计您的服务。