如何在启动Windows服务之前延迟5分钟?

8
我正在使用 .Net 4 构建一个简单的 Windows 服务,但当我想在启动服务前延迟 5 分钟时出现了问题。
protected override void OnStart(string[] args)
{
    // make a 5 min delay
    // do something
}

但是几秒钟后,服务停止并给出超时错误(在事件日志中看到)。 我应该怎么办?

8个回答

7

在新线程中启动您的长时间运行的进程,这样就不会阻塞 OnStart 方法。 例如:

using System.Threading;

protected override void OnStart(string[] args)
{
    ThreadPool.QueueUserWorkItem(new WaitCallback((_) =>
    {
        Thread.Sleep(5 * 1000 * 60);//simulate 5 minutes work

       // do something
    }));
}

1
是的,很好的想法。忽略操作系统中的Windows延迟服务启动选项,然后手动编码解决它们。 - TomTom
@TomTom:是的,好主意。忽略操作系统中的Windows延迟服务启动选项,然后手动编码解决它们。那么为什么会有-1呢?你是不是误操作了? - Jalal Said
2
TomTom,你确定所有版本的Windows都支持延迟服务选项吗?因为我正在使用Windows 2003。 - Ehsan Zargar Ershadi
不,只有当前的版本。2003年已经相当过时了。 - TomTom
1
@TomTom:2003年的扩展支持还有4年。我们并不总能选择我们使用什么,或者客户使用什么。 - Joe
@Incognito:我对你的评论感到困惑,“OnStart必须尽快返回”这正是我在这里所做的。我立即启动线程并将整个工作包装在其中,因此“OnStart”会立即返回。 - Jalal Said

3
不行。服务必须在被请求时启动。OnStart 必须快速返回。
也就是说,服务可以等待5分钟,直到它执行某些操作,但您不能停止启动循环。
启动它,然后让工作线程等待,直到它执行某些操作。
也就是说,有一个配置项允许延迟启动服务。它是针对服务配置的,就像手动、自动一样,有一个延迟条目。这可以确保服务仅在机器从启动中恢复一点时间后才启动。这可能更好/足够好。

能否请您更详细地解释一下配置项?谢谢。 - Ehsan Zargar Ershadi
打开Windows服务配置,查看选项,使用谷歌。不难,来吧。让我来做。谷歌搜索“Windows服务延迟启动”,第二个条目是... http://www.techrepublic.com/blog/datacenter/delayed-start-feature-increases-options-for-windows-services/1552 - TomTom
@TomTom 这是个不错的解决方案,但它只支持Win7、Vista和2008服务器... - Incognito

2

OnStart方法需要及时返回,否则会出现超时错误。

你需要在OnStart方法中启动一个线程,在该线程中等待5分钟后再实际启动服务。因此,你的OnStart方法变成了:

serviceThread = new Thread(new ThreadStart(workerClass.WorkerMethod));

serviceThread.Start();

WorkerClass.WorkerMethod 实际上启动了服务。


1

当服务被告知启动或Windows认为其出现故障时,它必须做出响应。因此,您有两个选择:

  1. 编写一个单独的应用程序,在启动时运行,等待5分钟,然后启动服务。

  2. 启动服务,并在它开始执行任何业务逻辑之前延迟5分钟。只要Windows认为它正常启动,它就很高兴。

类似于这样:

private static Timer t;
protected override void OnStart(string[] args)
{
    t = new Timer(5000*60);
    t.Elapsed += new ElapsedEventHandler(OnTimedEvent)
    t.Start()
}

private static void OnTimedEvent(object source, ElapsedEventArgs e)
{
    // real code here
}

1

我不明白为什么你想要延迟你的服务启动例程5分钟。如果服务例程需要更长时间,服务控制管理器可能会中止所有操作,因此你的服务无法启动。你最好需要在OnStart方法内启动一个线程/定时器,并在线程/定时器过程中等待5分钟。

protected override void OnStart(string[] args)
        {              
            Thread processor= new Thread(ThreadProc);
            processor.Start();
        }

        private void ThreadProc()
        {
            while (true)
            {
                Thread.Sleep(TimeSpan.FromMinutes(5));

            }
        }

1
使用System.Timers.Timer来推迟你的操作...这是我其中一个服务中的代码。我使用推迟的原因是因为Windows假设如果从onstart事件返回的时间太长,则服务会出现问题。由于我在服务启动时要做很多事情,所以我只用创建一个计时器快速启动服务,然后让该事件处理真正的启动工作。
    protected override void OnStart(string[] args)
    {
        try
        {
            // Using a timer Event to start asynchronously
            StartupTimer = new Timer();
            StartupTimer.Elapsed += StartupTimer_Elapsed;
            StartupTimer.AutoReset = false;
            StartupTimer.Interval = 5*60*1000;
            StartupTimer.Start();
        }
        catch (Exception ex)
        {
            LogMessage(true, ex.ToString());
        }
    }

    private void StartupTimer_Elapsed(object sender, ElapsedEventArgs e)
    {
        try
        {
            RunSetup(true);
        }
        catch (Exception ex)
        {
            LogMessage(true, ex.ToString());
        }
    }

0
一个简单的方法是使用 System.Threading.Timer 并将其到期时间设置为 5 分钟,请参见 System.Threading.Timer 获取更多信息。

0
问题的根源在于,如果服务启动需要很长时间,Windows 就会认为它出现故障并将其关闭。
您可以通过首先告知 Windows 此服务需要一些时间才能启动来解决此问题。
要做到这一点,请参见此 SO 问题的答案:windows service startup timeout

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接