C# 当我从windows C服务中选择停止时,windows服务将不会停止
我已经编写了一个windows服务,但是当我尝试停止该服务时,它会说此时无法停止该服务。这是我的全班同学:C# 当我从windows C服务中选择停止时,windows服务将不会停止,c#,windows-services,backgroundworker,C#,Windows Services,Backgroundworker,我已经编写了一个windows服务,但是当我尝试停止该服务时,它会说此时无法停止该服务。这是我的全班同学: public partial class RenewalsService : ServiceBase { private readonly ManualResetEvent _shutdownEvent = new ManualResetEvent(false); private Thread _thread; public RenewalsService()
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();
}
}
}
确保用户可以停止服务所缺少的内容。我认为您的代码没有问题,所以这里有几点需要检查 首先,GenerateNewal方法是否需要很长时间才能完成?如果是这样,您可能需要定期检查该方法中的_shutdownEvent,以便及时关闭。当然,您已经将该线程标记为后台线程,因此当您告诉服务停止时,它应该关闭。我还没有看到后台线程阻止进程终止,但我想总有这种可能性 第二,对我来说,更可能的罪魁祸首是服务已经因为异常而关闭。当服务关闭时,服务控制台不会自动刷新,因此您可能会看到停止链接在不应该关闭时可用。如果您点击F5,控制台将刷新,如果您的服务已停止,则Start链接应该是唯一可用的链接。检查日志文件以查看是否触发了异常处理程序 使现代化 因此,看起来WorkerThread方法正在引发异常,导致服务停止。这解释了为什么当您单击“停止”链接时会显示错误消息 如果您对设备具有足够的权限,请使用此选项调试您的服务,以找出发生异常的原因 HTH当SCM的Windows服务控制管理器向服务发送停止命令时,基本ServiceBase类在顶部调用重写的虚拟方法。在该方法的实现中,您应该执行使服务处于停止状态所需的任何操作,然后从该方法返回到ServiceBase类,该类处理与SCM的交互,在本例中告诉SCM您的服务现在已停止。SCM将决定何时终止服务进程,ServiceBase类将在您不需要执行任何显式操作的情况下处理该事务 对于行为良好的服务,您应该在OnStop方法的末尾返回,或者抛出异常。ServiceBase类将适当地处理事情,包括将异常(如果您抛出了异常)作为错误记录在Windows事件日志中。如果您的方法可能需要一段时间才能停止服务,则应在适当的时间点调用base.RequestAdditionalTime,以便基类可以告诉SCM您没有挂起,您的服务正在停止 我认为你的主要问题在于这些方面:
Environment.ExitCode = 0;
Environment.Exit(Environment.ExitCode);
你再也不会回到基类了。。。所以ServiceBase类从来没有机会优雅地响应SCM。。。您只是单方面终止承载服务的进程。这不是行为良好的Windows服务所做的
ServiceBase类被设计为能够支持在单个服务进程中承载的多个服务。单个服务不应该关心主机服务进程的生命周期,而应该只关心它们自己服务的逻辑状态。我在while循环之外添加了对onStop事件的调用。这似乎在某种程度上解决了这个问题。也就是说,它现在关闭服务,但抛出一个错误。忽略错误,然后服务停止。我还是不明白为什么。我已经检查了所有日志,包括事件查看器中的日志,所有日志看起来都正常。我可以接受当按下“停止”按钮时get抛出的错误,但最好能弄清原因。根据您的评论更新了我的答案。