我已经编写了一个Windows服务,但是当我尝试停止服务时,它表示此时服务无法停止。这是我的全班:
public partial class RenewalsService : ServiceBase
{
private readonly ManualResetEvent _shutdownEvent = new ManualResetEvent(false);
private Thread _thread;
public RenewalsService()
{
InitializeComponent();
this.CanStop = true;
}
protected override void OnStart(string[] args)
{
_thread = new Thread(WorkerThread)
{
Name = "Renewals Service Thread",
IsBackground = true
};
_thread.Start();
}
protected override void OnStop()
{
try
{
if (!_shutdownEvent.SafeWaitHandle.IsClosed)
{
_shutdownEvent.Set();
}
if (_thread.IsAlive)
{
if (!_thread.Join(3000))
{
// give the thread 3 seconds to stop
_thread.Abort();
}
}
}
catch (Exception ex)
{
// _thread.Join may raise an error at this point. If it does we dont care. We dont care about any other exceptions
// since we are already in the process of closing the service.
}
finally
{
IError logger = new Logger();
Exception ex = new Exception("The Renewals service has been stopped.");
logger.Log(this, SeverityEnum.Warning, ex);
Environment.ExitCode = 0;
Environment.Exit(Environment.ExitCode);
}
}
private void WorkerThread()
{
try
{
while (!_shutdownEvent.WaitOne(1))
{
string timeToRun = ConfigurationManager.AppSettings["RunTime"];
string[] timeStrings = timeToRun.Split(':');
TimeSpan runtime = new TimeSpan(0, Int32.Parse(timeStrings[0]), Int32.Parse(timeStrings[1]), Int32.Parse(timeStrings[2]));
if (DateTime.Today.TimeOfDay.Hours == runtime.Hours &&
DateTime.Today.TimeOfDay.Minutes == runtime.Minutes)
{
Renewals renewals = new Renewals();
renewals.GenerateRenewal();
}
}
}
catch (Exception ex)
{
IError logger = new Logger();
logger.Log(this, SeverityEnum.Warning, ex);
this.OnStop();
}
}
}
确保用户可以停止服务缺少什么。
答案 0 :(得分:0)
您的代码对我来说没问题,所以这里有几件事需要检查。
首先,GenerateRenewal()
方法需要很长时间才能完成吗?如果是这样,您可能需要定期检查该方法中的_shutdownEvent
以便及时关闭。当然,您已将该主题标记为后台主题,因此当您告诉服务停止时, 应该 关闭。我还没有看到后台线程阻止进程终止,但我想总有那种机会。
其次,对我来说更可能的罪魁祸首是该服务已因异常而关闭。当服务关闭时,服务控制台不会自动刷新,因此您可以在不应该看到停止链接的情况下看到它。如果按F5,控制台将刷新,如果您的服务已停止,则Start链接应该是唯一可用的。检查日志文件以查看是否已触发异常处理程序。
所以看起来你的WorkerThread()
方法抛出异常,导致服务停止。这解释了为什么Stop链接在您单击时会显示错误消息。
如果您拥有足够的权限,请使用此link调试您的服务,以找出发生异常的原因。
HTH
答案 1 :(得分:0)
当Windows服务控制管理器(“SCM”)向服务发送“停止”命令时,基类ServiceBase
类会调用重写的虚方法OnStop()
。在方法的实现中,你应该做任何必要的事情来使你的服务停止状态,然后从方法返回到ServiceBase
类,它处理与SCM的交互,在这种情况下告诉您的服务现已停止的SCM。 SCM将决定何时终止您的服务进程,ServiceBase
类处理该问题而无需您做任何明确的事情。
对于行为良好的服务,您应该在OnStop
方法结束时返回,或者抛出异常。 ServiceBase
类将适当地处理事情,包括在Windows事件日志中记录异常(如果已抛出异常)。如果您的方法可能需要一段时间才能停止服务,您应该在适当的位置调用base.RequestAdditionalTime()
,这样基类可以告诉SCM您还没有挂起,您的服务正在停止
我认为你的主要问题在于以下几点:
Environment.ExitCode = 0;
Environment.Exit(Environment.ExitCode);
你永远不会回到基类...所以ServiceBase
类永远不会有机会对SCM做出优雅的回应......你只是单方面终止托管服务的过程。这不是一个表现良好的Windows服务。
ServiceBase
类旨在支持在单个服务进程中托管的多个服务。各个服务不应该关注主机服务进程的生命周期,只关注自己服务的逻辑状态。