每x秒呼叫/启动Windows服务的最佳方法是什么?

时间:2009-05-15 06:05:01

标签: asp.net windows-services wcf

我有一个Windows服务,基本上是访问邮箱和阅读电子邮件。我试图找出每隔x秒检查一次邮箱的最佳方法。

一种方法是调用Thread.Sleep,然后再次调用Start方法,例如

protected override void OnStart(string[] args)
{
    // get config settings
    CheckMailbox();
}

public void CheckMailbox()
{
    int x = 5000;

    // do stuff

    Thread.Sleep(x);
    CheckMailbox();
}

不确定这是否是最好的方法。为了进一步探讨这一点,我了解您可以通过WCF公开服务来调用Windows服务。在这种情况下,如果一个名为Process的Web应用程序启动,那么我会纠正Threads吗?那我怎么处理呢?我是否每次都必须创建一个新线程并将其放入队列?

6 个答案:

答案 0 :(得分:7)

睡觉通常是一个坏主意。除此之外,它意味着您不会快速响应Stop事件。

您应该使用Timer。有两个适合服务:

在每种情况下,您基本上都会说出每次定时器“滴答”以及何时需要触发时您想要发生的事情。

我的线程教程有section explaining some of the differences between available timers

我不确定您的WCF问题,但我不认为您的Web服务会明确启动该服务 - 它只是通过WCF联系它。是的,你可能需要小心线程。您需要注意的正是取决于WCF服务所暴露的内容。

答案 1 :(得分:1)

Basic System.Threading.Timer代码:

// Class level variable in the Windows Service:
private System.Threading.Timer timer;

// This is in the constructor for a Windows Service.
// interval would be the time in milliseconds in between ticks.
// 0 is how long until it should start.
timer = new Timer(new TimerCallback(TimerElapsed), null, 0, interval);

// The TimerCallback in the Windows Service:
private void TimerElapsed(object o)
{
    // Do email stuff here.
}

答案 2 :(得分:0)

如果你想让它作为服务运行(在后台,没有任何人登录),是的,这是一种方法。

另一种方法是让Timer每隔5秒左右调用一次“Tick”事件处理程序。

或者,如果您的检查不是那么频繁,您还可以创建一个命令行控制台应用程序,并将其安排为Windows中的“计划任务”。

马克

答案 3 :(得分:0)

您的代码存在为每次调用添加到调用堆栈的问题,因为您从内部调用该方法。在某些时候,您将获得堆栈溢出异常。一个等待是在“等待线程”上调用另一个方法,该方法将在一段时间后发回信号:

private void CheckMailBox()
{
    _waitHandle = new AutoResetEvent(true);
    while (_waitHandle.WaitOne())
    {
        // do the mail checking
        ((IDisposable)_waitHandle).Dispose();
        _waitHandle = new AutoResetEvent(false);
        ThreadPool.QueueUserWorkItem(WaitSomeTime, 2000);
    }

}

private void WaitSomeTime(object state)
{

    Thread.Sleep((int)state);
    _waitHandle.Set();
}

答案 4 :(得分:0)

除了使用计时器之外的可能增强功能是在您的服务中使用计划组件。然后,您可以将服务设置为访问您的邮箱的代码的主机。

Quartz.NET是一个可以执行此操作的开源调度组件。它允许您完全按照自己的意愿设置调度,并且使用起来非常简单。

答案 5 :(得分:0)

好的,虽然您的计时问题已得到很好处理(我同意上述大部分内容),但我可以提供一些有关WCF的信息。 WCF服务仅托管在应用程序域中。该域可以是Windows窗体,控制台应用程序,ASP.net,在本例中是Windows服务。

从某种意义上说,你没有通过 WCF 公开 Windows服务,你在Windows服务中更多托管WCF服务应用程序域。在转换到Windows服务之前,我建议在 Windows窗体中测试您的服务(包括计时器对象)。更容易调试和测试。

托管的WCF服务实际上是在自己的线程中运行:

    serviceType_MyEmailer = typeof(MyEmailerServiceType);
    ServiceHost host_MyEmailer;


    host_MyEmailer = new ServiceHost(serviceType_MyEmailer);

在线查找“DerivativesCalculatorService”示例。向您展示如何在代码中托管WCF服务。

这里的时间技巧在于您的服务本身。您可以将服务类创建为立即初始化的单例类,并在初始化时可以启动其Timer对象(如其他答案所示)。

通过这种方式,您的WCF服务将具有类的持久实例,其Timer对象将以静默方式关闭。将所有内容托管在Windows服务中,您就完成了。

希望这有帮助。