【问题标题】:background worker with windows service具有 Windows 服务的后台工作人员
【发布时间】:2012-05-25 12:45:30
【问题描述】:

我正在使用 C# 在 Visual Studio 2010 中创建 Windows 服务,并且我有几个方法,如 Add、Multiply 和其他方法,我将它们放入 onStart 方法中。现在,我希望这些方法每五分钟运行一次。那么后台工作进程将如何帮助我呢?

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

【问题讨论】:

  • 我认为System.Timers.Timer 可能会更有帮助。后台工作者对于在另一个线程中工作而不阻塞当前线程(如 UI 线程)很有用。
  • 好的,谢谢,那么让我继续使用计时器
  • 可能,您可能想参考这个 - programmers.stackexchange.com/questions/80997/…
  • 如果您需要精确的精度(例如,该方法应在 n 分钟后准确执行),请尝试 Quartz.NET:google.co.in/…
  • @vcsjones:我相信 piyush 会在 Windows 服务中做到这一点,所以他可能想使用 System.Threading.Timer

标签: c# windows-services


【解决方案1】:

计时器是正确的方法。我有一个稍微增强的版本,它负责在 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 var,您可以让自己运行代码 作为一个程序,然后当你准备好测试你的关机逻辑时,只需打破所有和 设置完成为真。我多年来一直在使用这种方法并取得了很大的成功。

如代码中所述,如果您在计时器事件中做任何冗长的事情,那么您可能希望从 OnStop 对其进行监控,以确保它有足够的时间(如果在中间关闭)。

【讨论】:

    【解决方案2】:

    将这些函数封装在一个类中并在该类中创建一个 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();
        }
    
    }
    

    【讨论】:

      【解决方案3】:

      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();
          }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-04-14
        • 1970-01-01
        • 2013-03-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多