定期运行的Windows服务

Jos*_*osh 22 c# multithreading windows-services backgroundworker

我正在编写一个Windows服务,一旦启动就会每X小时运行一次.它完成的过程相当密集,所以我想使用后台工作程序.我正在使用设置文件来存储运行和上次运行服务之间的小时数.

我不确定最好的方法 - 也就是说,我希望服务尽可能少地使用资源,当它运行时,它需要在后台工作程序中运行,报告它做了什么,然后回到空闲模式.

我考虑过使用2名背景工作者.第一个worker是服务的私有局部变量,运行如下:

while (true)
{
      //create new background worker and run

      Thread.Sleep(Settings.Default.SleepTimeHours * 3600000);
}
Run Code Online (Sandbox Code Playgroud)

使用在循环的每次迭代中创建的子工作程序,并在完成时销毁.为了支持取消,我想我必须在服务中有第二个工作者的本地实例,但如果当前进程没有运行,它将为null.当辅助工作程序完成时,它将发送我的报告,在设置文件中设置上次运行时间,然后处理该工作程序并将引用设置为null.

我想知道是否有更好的方法来做这个或最好的做法.

谢谢

Cit*_*ane 34

我通常使用Timer,然后在进程开始运行时停止它.

这是一篇解释如何操作的文章.

  • 修复死链接 (2认同)

mar*_*c_s 15

这不是一个好主意,因为你在整个"SleepTimeHours"期​​间锁定了你的线程,在此期间你甚至无法停止服务.

您可以制作此服务,使其睡眠时间为5秒,然后检查是否需要重新开始工作,如果没有,再睡5秒钟(如果您需要停止,则可以提供必要的响应)服务).

或者:您可能最好只编写一个可以使用Windows"计划任务"功能进行安排的控制台应用程序,以便每x小时运行一次.这样,如果您的应用没有做任何事情,您将不会阻止或使用任何系统资源......

  • 没有睡完整个X小时的好点.谢谢,马克. (3认同)

Aus*_*nen 10

考虑像Quartz.Net这样的作业调度程序.

http://quartznet.sourceforge.net/


Ian*_*Ian 7

怎么样更像这样的东西:

    public class LongRunningService : ServiceBase
{
    System.Threading.Thread processThread;
    System.Timers.Timer timer;
    private Boolean Cancel;

    protected override void OnStart(string[] args)
    {
        timer = new Timer(Settings.Default.SleepTimeHours * 3600000);
        timer.Elapsed += new ElapsedEventHandler(timer_Tick);
        timer.Start();

        Cancel = false;
    }

    protected override void OnContinue()
    {
        timer.Start();
    }

    protected override void OnPause()
    {
        timer.Stop();
    }

    protected override void OnStop()
    {
        if (processThread.ThreadState == System.Threading.ThreadState.Running)
        {
            Cancel = true;
            // Give thread a chance to stop
            processThread.Join(500);
            processThread.Abort();
        }
    }

    void timer_Tick(object sender, EventArgs e)
    {
        processThread = new System.Threading.Thread(new ThreadStart(DoWork));
        processThread.Start();
    }

    private void DoWork()
    {
        try
        {
            while (!Cancel)
            {

            if (Cancel) { return; }
            // Do General Work

            System.Threading.Thread.BeginCriticalRegion();
            {
                // Do work that should not be aborted in here.
            }
            System.Threading.Thread.EndCriticalRegion();
            }

        }
        catch (System.Threading.ThreadAbortException tae)
        {
            // Clean up correctly to leave program in stable state.
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


Mat*_*vis 5

使用基于System.Threading.WaitHandle方法的方法.

using System.Threading;
private Thread _thread;
private ManualResetEvent _shutdownEvent = new ManualResetEvent(false);
private ManualResetEvent _scheduleEvent = new ManualResetEvent(false);
private System.Timers.Timer _scheduleTimer = new System.Timers.Timer();
protected override void OnStart(string[] args)
{
    // Configure the timer.
    _scheduleTimer.AutoReset = false;
    _scheduleTimer.Interval = 120000; // 2 minutes in milliseconds
    _scheduleTimer.Elapsed += delegate { _scheduleEvent.Set(); }

    // Create the thread using anonymous method.
    _thread = new Thread( delegate() {
        // Create the WaitHandle array.
        WaitHandler[] handles = new WaitHandle[] {
            _shutdownEvent,
            _scheduleEvent
        };
        // Start the timer.
        _scheduleTimer.Start();
        // Wait for one of the events to occur.
        while (!_shutdownEvent.WaitOne(0)) {
            switch (WaitHandle.WaitAny(handles)) { 
               case 0:  // Shutdown Event
                   break;
               case 1:  // Schedule Event
                   _scheduleTimer.Stop();
                   _scheduleEvent.Reset();
                   ThreadPool.QueueUserWorkItem(PerformScheduledWork, null);
                   break;
               default:
                   _shutdownEvent.Set(); // should never occur
            }
        }
    } );
    _thread.IsBackground = true;
    _thread.Start();
}
protected override void OnStop()
{
    // Signal the thread to shutdown.
    _shutdownEvent.Set();
    // Give the thread 3 seconds to terminate.
    if (!_thread.Join(3000)) {
        _thread.Abort(); // not perferred, but the service is closing anyway
    }
}
private void PerformScheduledWork(object state)
{
    // Perform your work here, but be mindful of the _shutdownEvent in case
    // the service is shutting down.
    //
    // Reschedule the work to be performed.
     _scheduleTimer.Start();
}
Run Code Online (Sandbox Code Playgroud)