如何在不使用Timer的情况下在Windows服务中进行循环

时间:2010-01-09 08:26:09

标签: c# windows-services

我希望每隔10秒从Windows服务(使用C#和.NET完成)调用Business层方法。但是,我不想使用Timer_Elapsed事件,因为如果第一个线程/进程仍在运行,它将启动另一个线程/进程。我只需要一个单线程方法,因为对同一个Business方法的多次调用会产生不必要的复杂情况。

所以我在on_start中添加了一个do-while循环。我知道这不是正确的方法,因为它会产生这个过程,如果服务被关闭,它就会成为一个孤儿。

我如何解决这个问题?

此致 泽

5 个答案:

答案 0 :(得分:45)

还有另一种获取定时执行的方法,WaitHandle.WaitOne()方法提供了一个超时参数。这在服务中非常有效,因为它允许您在单个方法调用中实现停止服务定期执行的需要。模板看起来像这样:

    Thread Worker;
    AutoResetEvent StopRequest = new AutoResetEvent(false);

    protected override void OnStart(string[] args) {
        // Start the worker thread
        Worker = new Thread(DoWork);
        Worker.Start();
    }
    protected override void OnStop() {
        // Signal worker to stop and wait until it does
        StopRequest.Set();
        Worker.Join();
    }
    private void DoWork(object arg) {
        // Worker thread loop
        for (;;) {
            // Run this code once every 10 seconds or stop right away if the service 
            // is stopped
            if (StopRequest.WaitOne(10000)) return;
            // Do work...
            //...
        }
    }

答案 1 :(得分:4)

使用计时器,但只要输入Timer处理程序方法,就禁用计时器,以便不再引发事件。在退出处理程序之前,重新启用计时器。

答案 2 :(得分:4)

查看this discussion,特别是jsw的回答。它建议了一种同步机制,以防止多次同时调用业务逻辑。由于在单独的线程上调用处理程序,因此无法保证在Elapsed处理程序方法中禁用计时器会阻止并行调用。使用jsw建议的锁定,并在同步代码块中停止计时器。

或者,您可以使用Timer并将AutoReset属性设置为false。这样,Elapsed事件只会被引发一次,您可以在处理程序方法结束时手动重置计时器。

答案 3 :(得分:-2)

while(true)
    {
     ..do something
     Thread.sleep( some time or day);
    }

答案 4 :(得分:-2)

    Thread thread;
    private void DoWork(object arg)
    {
        while (true)
        {
            // Run this code once every 20 seconds or stop if the service is stopped
            try
            {
                Thread.Sleep(20000);
                //Do work....
            }
            catch(ThreadInterruptedException)
            {
                return;
            }

        }
    }

    protected override void OnStart(string[] args)
    {
        // Start the thread
        thread = new Thread(DoWork);
        mWorker.Start();
    }

    protected override void OnStop()
    {
        // interrupt thread and wait until it does
        thread.Interrupt();
        thread.Join();
    }