使用Windows服务的后台工作程序

3

我正在使用C#在Visual Studio 2010中创建一个Windows服务,其中有一些方法,如AddMultiply等,我将它们放在onStart方法中。现在,我希望这些方法每隔五分钟运行一次。那么后台工作进程如何帮助我实现这个目标呢?

protected override void OnStart(string[] args)
{
    add(); // yes, it doesn't have parameters      
}

3
我认为 System.Timers.Timer 更有帮助。BackgroundWorker 适合在另一个线程中完成工作而不会阻塞当前线程(如UI线程)。 - vcsjones
好的,谢谢。那我就继续讲定时器了。 - Piyush Sardana
也许你想参考这个链接 - http://programmers.stackexchange.com/questions/80997/multi-threading-in-c-net-windows-service - Angshuman Agarwal
@vcsjones:我相信Piyush会在Windows服务中完成这个任务,所以他可能想要使用System.Threading.Timer。 - Sudhanshu Mishra
3个回答

5

将这些功能封装到一个类中,并在该类中创建一个System.Timers.Timer(),并在定时器中调用所有这些函数。在服务的OnStart中调用NewClass示例类的Start()函数。

class NewClass
{
 this._watcherTimer = new System.Timers.Timer();
 this._watcherTimer.Interval =  60000;
 this._watcherTimer.Enabled=False;
 this._watcherTimer.Elapsed += new System.Timers.ElapsedEventHandler(this.Timer_Tick);


 public void Start()
{
 this._watcherTimer.Enabled=true;

}


 private void Timer_Tick(object sender, EventArgs e)
    {
        Add();
        Multiply();
    }

}

5
计时器是正确的选择。我有一个稍微增强版的计时器,它在OnStop方法中负责关闭计时器。
在你的program.cs中,为了使调试更容易,我会执行以下操作:
using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceProcess;
using System.Text;
using System.Threading;

namespace SampleWinSvc
{
  static class Program
  {
    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    static void Main()
    {
#if (!DEBUG)
      ServiceBase[] ServicesToRun;
      ServicesToRun = new ServiceBase[] { new Service1() };
      ServiceBase.Run(ServicesToRun);
#else
      //Debug code: this allows the process to run 
      // as a non-service. It will kick off the
      // service start point, and then run the 
      // sleep loop below.
      Service1 service = new Service1();
      service.Start();
      // Break execution and set done to true to run Stop()
      bool done = false;
      while (!done)
        Thread.Sleep(10000);
      service.Stop();
#endif
    }
  }
}

然后,在你的Service1.cs代码中:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.ServiceProcess;
using System.Timers;
using System.Text;

namespace SampleWinSvc
{
    public partial class Service1 : ServiceBase
    {
        /// <summary>
        /// This timer willl run the process at the interval specified (currently 10 seconds) once enabled
        /// </summary>
        Timer timer = new Timer(10000);

        public Service1()
        {
            InitializeComponent();
        }

        protected override void OnStart(string[] args)
        {
            Start();
        }

        public void Start()
        {
            // point the timer elapsed to the handler
            timer.Elapsed += new ElapsedEventHandler(timer_Elapsed);
            // turn on the timer
            timer.Enabled = true;
        }

        /// <summary>
        /// This is called when the service is being stopped. 
            /// You need to wrap up pretty quickly or ask for an extension.
        /// </summary>
        protected override void OnStop()
        {
            timer.Enabled = false;
        }

            /// <summary>
            /// Runs each time the timer has elapsed. 
            /// Remember that if the OnStop turns off the timer, 
            /// that does not guarantee that your process has completed. 
            /// If the process is long and iterative, 
            /// you may want to add in a check inside it 
            /// to see if timer.Enabled has been set to false, or 
            /// provide some other way to check so that 
            /// the process will stop what it is doing.
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
        void timer_Elapsed(object sender, ElapsedEventArgs e)
        {
            MyFunction();
        }

        private int secondsElapsed = 0;
        void MyFunction()
        {
            secondsElapsed += 10;
        }
    }
}

通过在编译选项中设置#DEBUG变量,您允许自己将代码运行为程序,然后当您准备测试关闭逻辑时,只需打断所有并将done设置为true。多年来,我一直使用这种方法取得了很大的成功。
如代码中所述,如果您在计时器事件中执行任何冗长的操作,则可能希望从OnStop监视它,以确保在关机过程中有足够的时间来完成。

2

使用Backgroundworker的另一个可能解决方案:

public partial class Service1 : ServiceBase
{
    private System.ComponentModel.BackgroundWorker bwMyWorker;
    public Service1()
    {
        InitializeComponent();
    }

    protected override void OnStart(string[] args)
    {
        bwMyWorker = new BackgroundWorker();            
        bwMyWorker.DoWork += delegate(object sender, DoWorkEventArgs workArgs)
        {
            //Endless loop
            for (; ; )
            {
                //Your work... E.g. add()
                System.Threading.Thread.Sleep(new TimeSpan(0, 5, 0)); //Pause for 5 min
            }

        };
        bwMyWorker.RunWorkerAsync();
    }

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