Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/273.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 当我从windows C服务中选择停止时,windows服务将不会停止_C#_Windows Services_Backgroundworker - Fatal编程技术网

C# 当我从windows C服务中选择停止时,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()

我已经编写了一个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();

        }

    }
}

确保用户可以停止服务所缺少的内容。

我认为您的代码没有问题,所以这里有几点需要检查

首先,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抛出的错误,但最好能弄清原因。根据您的评论更新了我的答案。