Windows 服务中使用 Timer 控件时,Tick 事件不命中问题的解决

来源:互联网 发布:图片标注软件 编辑:程序博客网 时间:2024/06/10 03:59

Windows 服务中使用 Timer 控件时,Tick 事件不命中问题的解决

首先我们要分清一下两个 Timer 类,
System.Timers.Timer
System.Windows.Forms.Timer

估计现在大多数人都能明白问题产生的原因了吧!
其中在工具箱中默认存在的那个 Timer 控件,引用的是
System.Windows.Forms.Timer 类。

如果在写windows 服务时,使用的是在工具箱中添加的 Timer 控件,
那你就中奖了!(Tick 事件永远不会不命中。任凭你怎么调试,
它是不报异常并且也能编译通过)

现在就把windows 服务中的 Timer 改成 System.Timers.Timer 类吧!
需要注意的是两个类的“命中事件”是不一样的。
System.Timers.Timer.Elapsed
System.Windows.Forms.Tick
到这里,Tick 事件不命中问题的解决了。

下面是封装定时调用的一个组件类的代码
相信我们经常会遇到这样一种需求,就是“定时调用”而不是“间隔调用”
想设定一个或多个时间,每天定时执行相关代码。
下面我封装了一个支持“定时调用"和"间隔调用"的组件。
代码放到下面了。
注意:如果开启定时调用,则间隔调用将不起作用


-----------------------------------------------------------
-- WinServiceTimer.cs 文件
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Timers;
using Tt.WinService.Bll;

namespace Tt.WinService.ExpressTrack
{
  /// <summary>
  /// Win 服务中使用 timer 组件
  /// 由于使用“工具箱”中的 Timer 在 Win 服务程序中不会命中,
  /// 故写一个 在 win 服务中的 Timer 组件
  /// </summary>
  public partial class WinServiceTimer : Component
  {
    public WinServiceTimer()
    {
      InitializeComponent();
      InitTimer();
    }

    public WinServiceTimer(IContainer container)
    {
      container.Add(this);

      InitializeComponent();
      InitTimer();
    }
    #region 事件
    public delegate void TimerTickHandler(object sender, WinServiceTimerEventAgrs e);
    /// <summary>
    /// 当Timer 计时器时间到达时发生
    /// </summary>
    public event TimerTickHandler OnTimerTick;
    #endregion

    #region 变量

    System.Timers.Timer m_timer = new System.Timers.Timer();
    /// <summary>
    /// 组件被触发的时间点集合
    /// </summary>
    private Timer[] m_invokeTime = null;
    /// <summary>
    /// 调用时间间隔
    /// </summary>
    private int m_invokeInterval = 30;
    /// <summary>
    /// 是否启用定时调用
    /// </summary>
    private bool m_EnableTimed = false;
    #endregion

    #region 控制timer组件属性
    /// <summary>
    /// 组件调用时间间隔(以‘分’为单位,取值 30-240)
    /// </summary>
    [Description("组件调用时间间隔(以‘分’为单位,取值 30-240)")]
    public int Interval
    {
      set
      {
        if (value < 30 || value > 240)
          throw new Exception("Interval 取值范围在 30-240 之间");

        m_invokeInterval = value;
        this.m_timer.Interval = m_invokeInterval * 60000;
      }
      get
      {
        return m_invokeInterval;
      }
    }
    /// <summary>
    /// 设置定时调用时间,同时需要设置 EnableTimed 为 true
    /// </summary>
    [Description("设置定时调用时间,同时需要设置 EnableTimed 为 true")]
    public Timer[] InvokeTime
    {
      set
      {
        if (value != null && value.Length > 0)
        {
          this.EnableTimed = true;
        }

        m_invokeTime = value;
      }
      get
      {
        return m_invokeTime;
      }
    }
    /// <summary>
    /// 是否启用定时调用
    /// </summary>
    [DefaultValue(false)]
    [Description("是否启用定时调用")]
    public bool EnableTimed
    {
      set
      {
        //如果是定时调用,需要设置 timer 为 1 分钟调用一次
        if (value)
        {
          this.m_timer.Interval = 60 * 1000;
        }
        else
        {
          this.m_timer.Interval = this.m_invokeInterval;
        }

        m_EnableTimed = value;
      }
      get
      {
        return m_EnableTimed;
      }
    }
    /// <summary>
    /// 获取或设置一个值,该值指示 System.Timers.Timer 是否应引发 System.Timers.Timer.Elapsed 事件。
    /// </summary>
    [Description("获取或设置一个值,该值指示 System.Timers.Timer 是否应引发 System.Timers.Timer.Elapsed 事件。")]
    public bool Enabled
    {
      set
      {
        this.m_timer.Enabled = value;
      }
      get
      {
        return this.m_timer.Enabled;
      }
    }
    #endregion

    #region 控制定时器
    /// <summary>
    /// 获取调用时间的字符串表示形式
    /// </summary>
    /// <returns></returns>
    public string GetInvokeTimeToString()
    {
      if (this.InvokeTime.IsNullOrDbNull())
        return string.Empty;

      string str = string.Empty;
      InvokeTime.All(o =>
      {
        if (str.IsNullOrEmpty())
          str += string.Format("{0}:{1}", o.Hour, o.Minute);
        else
          str += string.Format(",{0}:{1}", o.Hour, o.Minute);
        return true;
      });
      return str;
    }
    #endregion

    /// <summary>
    /// 初始化调用时间
    /// </summary>
    private void InitTimer()
    {
      //设置timer 调用时间 30 分钟
      this.m_timer.Interval = 30 * 60000;
    }
    /// <summary>
    /// 通过将 System.Timers.Timer.Enabled 设置为 true 开始引发 System.Timers.Timer.Elapsed
    /// 事件。
    /// </summary>
    public void Start()
    {
      this.m_timer.Elapsed += new ElapsedEventHandler(m_timer_Elapsed);
      this.m_timer.Start();

    }
    /// <summary>
    /// 通过将 System.Timers.Timer.Enabled 设置为 false 停止引发 System.Timers.Timer.Elapsed
    /// 事件。
    /// </summary>
    public void Stop()
    {
      this.m_timer.Stop();
    }
    /// <summary>
    /// 到达间隔时间时发生
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void m_timer_Elapsed(object sender, ElapsedEventArgs e)
    {
      WinServiceTimerEventAgrs agrs = new WinServiceTimerEventAgrs();
      agrs.EnableTimed = this.EnableTimed;
      //定时调用
      if (this.EnableTimed)
      {
        if (this.m_invokeTime.IsNullOrDbNull())
          return;
        DateTime currTime = DateTime.Now;
        foreach (Timer time in m_invokeTime)
        {
          if (currTime.Hour == time.Hour && currTime.Minute == time.Minute)
          {
            //定时调用
            if (OnTimerTick != null)
            {
              agrs.Time = time;
              agrs.InvokeTime = currTime;
              OnTimerTick(this, agrs);
            }
          }
        }
        return;
      }

      //普通间隔调用
      if (OnTimerTick != null)
      {
        agrs.InvokeTime = DateTime.Now;
        OnTimerTick(this, agrs);
      }
    }
  }
  /// <summary>
  /// win 服务事件参数
  /// </summary>
  public class WinServiceTimerEventAgrs:EventArgs
  {
    /// <summary>
    /// 定时调用的时间
    /// </summary>
    public Tt.WinService.ExpressTrack.Timer Time{ set;get; }
    /// <summary>
    /// 是否启用定时调用
    /// </summary>
    public bool EnableTimed { set; get; }
    /// <summary>
    /// 调用时间
    /// </summary>
    public DateTime InvokeTime { set; get; }

  }
}
-----------------------------------------------------------
-- Timer.cs 文件
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Tt.WinService.ExpressTrack
{
  /// <summary>
  /// 定时器
  /// </summary>
  public class Timer
  {
    private int m_hour = 1;
    private int m_minute = 0;
    /// <summary>
    /// 小时部分(1-23H)
    /// </summary>
    public int Hour
    {
      set
      {
        if (value < 1 || value > 23)
          throw new Exception("Hour 取值范围在 1-23H 之间");

        m_hour = value;
      }
      get { return m_hour; }
    }
    /// <summary>
    /// 分钟部分(0-59)
    /// </summary>
    public int Minute
    {
      set
      {
        if (value < 0 || value > 59)
          throw new Exception("Minute 取值范围在 0-59s 之间");

        m_minute = value;
      }
      get { return m_minute; }
    }
  }
}

---------------------------------------------
转载请保留:
http://write.blog.csdn.net/postedit/7565793

原创粉丝点击