C# 当Win service收到暂停或停止时,继续执行任务的最佳方式是什么?
因此,我成功地编写了该服务,目前它运行良好。假设我要确保在处理数据库记录时,以及由于某种原因,如果服务暂停或关闭,任务应该完成,而不是让数据不一致 我试过下面的代码,但我觉得它可能不正确,如果是,它可能不是最好的。如何针对上述场景改进此代码C# 当Win service收到暂停或停止时,继续执行任务的最佳方式是什么?,c#,.net,windows,service,windows-services,C#,.net,Windows,Service,Windows Services,因此,我成功地编写了该服务,目前它运行良好。假设我要确保在处理数据库记录时,以及由于某种原因,如果服务暂停或关闭,任务应该完成,而不是让数据不一致 我试过下面的代码,但我觉得它可能不正确,如果是,它可能不是最好的。如何针对上述场景改进此代码 protected override void OnStart(string[] args) { // Update the service state to Start Pending. ServiceStatus serviceStatu
protected override void OnStart(string[] args)
{
// Update the service state to Start Pending.
ServiceStatus serviceStatus = new ServiceStatus();
serviceStatus.dwCurrentState = ServiceState.SERVICE_START_PENDING;
serviceStatus.dwWaitHint = 100000;
SetServiceStatus(this.ServiceHandle, ref serviceStatus);
_eventLog.WriteEntry("RMS Service Started: " + DateTime.UtcNow.ToLongDateString());
CheckDBEntryData();
_timer = new System.Timers.Timer();
_timer.Interval = 60000;
_timer.Elapsed += new System.Timers.ElapsedEventHandler(this.SendScheduledSMS);
_timer.Start();
// Update the service state to Running.
serviceStatus.dwCurrentState = ServiceState.SERVICE_RUNNING;
SetServiceStatus(this.ServiceHandle, ref serviceStatus);
}
public void SendScheduledSMS(object sender, System.Timers.ElapsedEventArgs e)
{
if (!_isTaskRunning)
{
_timer.Enabled = false;
_isTaskRunning = true;
_eventLog.WriteEntry("RMS Timer Event started: " + DateTime.UtcNow.ToLongDateString());
//TODO: Write the code to check pending RMS and process them
_eventLog.WriteEntry("RMS Timer Event stopped: " + DateTime.UtcNow.ToLongDateString());
_isTaskRunning = false;
_timer.Enabled = true;
}
}
protected override void OnStop()
{
CanStop = !_isTaskRunning;
// Update the service state to Stop Pending.
ServiceStatus serviceStatus = new ServiceStatus();
serviceStatus.dwCurrentState = ServiceState.SERVICE_STOP_PENDING;
serviceStatus.dwWaitHint = 100000;
SetServiceStatus(this.ServiceHandle, ref serviceStatus);
_eventLog.WriteEntry("RMS Service Stopped: " + DateTime.UtcNow.ToLongDateString());
// Update the service state to Stopped.
serviceStatus.dwCurrentState = ServiceState.SERVICE_STOPPED;
SetServiceStatus(this.ServiceHandle, ref serviceStatus);
}
更多信息
服务正在处理数据库记录并将数据传递给第二个远程服务器,该服务器负责向用户发送SMS通知。我需要确保通知只发送一次。如果我使用事务,并且对最后一条记录进行回滚,则下次处理开始时,它将从开始发送通知,从而发送重复通知。因此,我不能依赖DB事务模式,因为我无法控制第二台远程服务器
在完成任何现有任务时,您需要定期设置服务状态,并适当减少等待提示
这里的“定期”需要一些猜测,但它需要足够频繁,以确保服务控制经理不会将您的服务视为未关闭。过去我每隔几秒钟就做一次,没有问题
如果您有任何需要花费很长时间(超过几十秒)才能完成的事情,您确实需要重新构造,以便在服务重新启动时恢复(请记住,关闭可能是因为系统即将断电或需要尽快停止)。服务可以随时突然停止。它可能会崩溃,或者电源中断。在上述任何情况下,结果都应一致。这就是为什么在与数据库交互时使用事务:在数据库处于一致状态时提交事务。如果发生中断(崩溃、SCM停止、断电等),DB将回滚到以前的一致状态
你试图修复SCM交互完全是找错了方向。您的重点应该放在数据库工作上,确保您的事务边界正确。这很有用,但不会解决问题,也就是说,此服务正在处理数据并向第二台服务器发送请求。第二台服务器将处理数据,如果我回滚并重做数据,这意味着我将再次处理相同的请求。在分布式事务中注册这两台服务器。或者使用可靠的消息传递协议。整个问题领域都得到了很好的研究和理解。尝试使服务“防故障”不是一个选项。我无法控制由ISP拥有的远程服务器。我使用windows服务通过他们提供的API进行调用,windows服务负责从DB获取记录并将其传递到远程服务器。我遇到了这个问题,但真正能够理解线程部分。如果SendScheduledSMS占用的时间超过了我在等待提示中设置的时间,会发生什么?如果代码仍在执行或花费的时间超出预期,我如何更新等待提示?@Hitin我没有说这很容易:这就是为什么不容易。您需要在一个线程上执行发送,同时在另一个线程上更新SCM(使用线程池:不要执行自己的线程管理),但是您还需要确定如果发送未完成该怎么办。
serviceStatus.dwCurrentState = ServiceState.SERVICE_STOP_PENDING;
serviceStatus.dwWaitHint = 100000;
SetServiceStatus(this.ServiceHandle, ref serviceStatus);