定期运行的Windows服务

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

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

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

while (true) { //create new background worker and run Thread.Sleep(Settings.Default.SleepTimeHours * 3600000); } 

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

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

谢谢

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

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

这不是一个好主意,因为您在整个“SleepTimeHours”期​​间锁定了线程,并且在此期间您甚至无法停止服务。

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

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

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

http://quartznet.sourceforge.net/

怎么样更像这样的东西:

  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. } } } 

使用基于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(); } 

你真的不想使用后台工作者。 当你在前台有一些东西(比如UI)并且你还想要在后台做其他事情时,会使用后台工作程序。 在您的情况下,没有前台处理,您所拥有的只是一个工作,您需要每隔一段时间运行一次。

此外,不要打扰睡眠业务等。而是使用调度程序框架,如Quartz.NET , 偶尔唤醒它。 这样,当您的服务启动时,它将初始化调度程序,并且在调度程序唤醒之前不会执行任何操作。 当调度程序唤醒时,它将调用一个对象的方法,在初始化时它会告诉它调用它。

这样,服务在空闲时几乎不消耗任何CPU,并在需要时全速运行。

Blog.StackOverflow.com有一篇关于使用缓存过期来处理周期性任务的有趣文章:

http://blog.stackoverflow.com/2008/07/easy-background-tasks-in-aspnet/

有人对超级用户提出了类似的问题。 您可以安装一个监视Windows服务的工具。 像Service Hawk这样的东西可以帮助您保持服务的启动,或者允许您安排自动重启(可能在夜间)以保持服务平稳运行。

在我的公司,我们依靠Windows任务调度程序来启动服务,然后让服务自行关闭。 这确保我们的服务始终在正确的时间运行,并且调度系统将允许报告成功/失败等。

使用计时器执行此操作。

我在1小时前和同事们进行了同样的讨论! 我选择了while(_isPolling)选项,因为我需要同步进行工作。 我不希望其他线程(Timer方法)接收相同的工作,并且实现额外的锁定似乎是浪费。

我应用了Timer和工作线程的组合,到目前为止它工作正常。

我设置我的计时器每分钟打勾,如果时间与计划时间匹配,我创建我的工作线程。

我用这种技术做了一些家务:

 if (nowTimeVar.ToShortTimeString().CompareTo(houseKeep.ToShortTimeString()) == 0) { myHouseKeeper = new clsHouseKeep(archiveFolder, lastday, myCounter, myLogger); } 

在检查了很多教程后,我开发了每隔60分钟定期运行的Windows服务,它将在后台启动进程并运行Test.exe。

 public partial class Scheduler : ServiceBase { private Timer timer1 = null; public Scheduler() { InitializeComponent(); } // Get the Exe path private string GetPath() { Assembly assembly = Assembly.GetExecutingAssembly(); return Path.Combine(Path.GetDirectoryName(assembly.Location), "Test.exe"); } // you can right your own custom code // Above vista version the process works as Administrator- "runas" and in old OS it will Start process as per Administartor rights public void startprocess() { // System.Diagnostics.Process.Start(GetPath()); System.Diagnostics.Process process = null; System.Diagnostics.ProcessStartInfo processStartInfo; processStartInfo = new System.Diagnostics.ProcessStartInfo(); processStartInfo.FileName = GetPath(); if (System.Environment.OSVersion.Version.Major >= 6) // Windows Vista or higher { processStartInfo.Verb = "runas"; } else { // No need to prompt to run as admin } processStartInfo.Arguments = ""; process = System.Diagnostics.Process.Start(processStartInfo); } // On start method will load when system Start // timer1_tick Event will call every hour after once start the service automatically protected override void OnStart(string[] args) { //System.Diagnostics.Debugger.Launch(); timer1 = new Timer(); this.timer1.Interval = 3600000; //every 60 min this.timer1.Elapsed += new System.Timers.ElapsedEventHandler(this.timer1_Tick); timer1.Enabled = true; } // Timer1_tick will Start process every hour private void timer1_Tick(object sender, ElapsedEventArgs e) { //Write code here to do some job depends on your requirement startprocess(); } // Method will stop the service // we have set the method stop service as false. so service will not stop and run every hour protected override void OnStop() { timer1.Enabled = false; } 

}