.NET 几种定时器的原理和部分使用示例

.NET 几种定时器的原理和部分使用示例

首先,目前.NET的定时器有三种:

1. System.Windows.Forms.Timer
从这个定时器的命名空间可以看出,.net设计这个定时器的目的是为了方便程序员在Window Form中使用的定时器。当一个System.Windows.Forms.Timer类被构造时,当前定时器会和当前线程进行关联。而当计时器的计满后,一个定时器消息将被插入到当前线程的消息队列中。当前线程逐一处理消息中的所有消息,并一一派发给各自的处理方法。这样的机制和利用工作者进程定时有很大的区别。

System.Windows.Forms.Timer类型并没有涉及多线程的操作,定时器的设置、定时方法的执行都在同一个线程之上。这就意味着System.Windows.Forms.Timer并不能准确计时,尤其当消息阻塞时,定时器的误差将会更大,因为定时器消息只能等待在前面的所有消息处理完后才能得到处理。但是因为System.Windows.Forms.Timer类型的定时器并不涉及多线程的操作,因此是线程安全的,不会发生回调方法重入的问题。
2. System.Threading.Timer
这个定时器类的使用相对复杂,但同时它也是最优化的非常常用的一个定时器类型。System.Threading.Timer的定时方法在独立的线程上执行,定时时间更为准确。使用回调方法的计时器,而且由线程池线程服务,简单且对资源要求不高。所有的对象有一个线程控制,当下一个定时到达时,该线程会负责在线程中获得一个新的工作者线程,用以执行相应的回调方法。

虽然这个定时器是相对最优化的一个定时器类型,但是从其机制上来讲,其并不是线程安全的,可能会出现回调方法重入的问题。解释下方法重入,是一个有关多线程编程的概念,意思大概是:同一程序中,多个线程同时运行时,就可能发生同一个方法被多个进程同时调用的情况。当这个方法中存在一些非线程安全的代码时,方法重入会导致数据发生同步错误的bug。
3. System.Timers.Timer
这是一个相对较旧的类型,它和System.Threading.Timer一样,可以由工作者线程来执行回调方法,但同时它也可以在IDE环境中被拖到窗体控件上,这个时候它的行为非常类似于System.Windows.Forms.Timer类型,在消息过多时其定时并不准确。  System.Timers.Timer可以视为System.Threading.Timer的一个包装,其类型设计相对古老,不建议使用该定时器。

简单来说,不管是哪种定时器,目的都是为了在某一(多个)时间段或者某一(多个)时间点,去执行一段逻辑代码来帮助我们完成某些需求

以下使用第三种定时器兼IIS来实现单件的例子
内容包括:声明,绑定,使用,判断,释放

using System;
using System.Collections.Generic;
using System.Linq;
using System.Timers;
using System.Web;
using System.Web.Mvc;
using System.Web.Optimization;
using System.Web.Routing;
using Data_BLL;
using Data_BLL.Data_Application;

namespace ZNKJ_FinancialStock
{
    #region 判断方法&&执行方法
    /// <summary>
    /// 每30秒判断一次 (根据时间段动态选择间隔时间)
    /// </summary>
    public static class Just_Do_It
    {
        public static void does(object source, ElapsedEventArgs e)
        {
            var now = DateTime.Now.TimeOfDay;///获取当前时间
            //判断当前时间是否在时间段内
            string _strWorkingDayAM = "23:55";//起始时间
            string _strWorkingDayPM = "23:56";//结束时间
            var dspWorkingDayAM = DateTime.Parse(_strWorkingDayAM).TimeOfDay;///获取当天时间格式 yyyy-MM-dd HH:mm:ss格式
            TimeSpan dspWorkingDayPM = DateTime.Parse(_strWorkingDayPM).TimeOfDay;///同理
            if (now> dspWorkingDayAM && now< dspWorkingDayPM)///如果在该时间段内
            {
                //这里写需要执行的代码
               
            }
        }
        /// <summary>
        /// 应用池回收的时候调用的方法
        /// </summary>
        public static void does()
        {
            回收时做什么
            HttpResponse.RemoveOutputCacheItem("路径","缓存名称");///清除缓存   可以不用
            return;
        }
    }
    #endregion

    /// <summary>
    /// 环境初始化
    /// </summary>
    public class MvcApplication : System.Web.HttpApplication
    {
        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);

            //声明定时器
            System.Timers.Timer myTimer = new System.Timers.Timer(30000);///单位毫秒  半分钟判断一次
            //TaskAction.SetContent 表示要调用的方法
            myTimer.Elapsed += new System.Timers.ElapsedEventHandler(Just_Do_It.does);
            myTimer.Enabled = true;
            myTimer.AutoReset = true;
        }

        /// <summary>
        ///  在会话结束时运行的代码。
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void Session_End(object sender, EventArgs e)
        {
            //下面的代码是关键,可解决IIS应用程序池自动回收的问题
            System.Threading.Thread.Sleep(30000); 
            //触发事件,执行判断方法
            Just_Do_It.does();
            //设置web地址,可以随便指向你的任意一个aspx页面甚至不存在的页面,目的是要激发Global.asax中的初始化Application_Start()   页面随便写,即使这个页面不存在
            string url = "";
            System.Net.HttpWebRequest myHttpWebRequest = (System.Net.HttpWebRequest)System.Net.WebRequest.Create(url);  ///主动建立连接
            System.Net.HttpWebResponse myHttpWebResponse = (System.Net.HttpWebResponse)myHttpWebRequest.GetResponse();  ///触发Start
            System.IO.Stream receiveStream = myHttpWebResponse.GetResponseStream();//得到返回的字节流    *
           
            // 注意: 只有在 Web.config 文件中的 sessionstate 模式设置为 InProc 时,才会引发 Session_End 事件。(默认即可) 
            // 如果会话模式设置为 StateServer或 SQLServer,则不会引发该事件。
        }
    }
}

接下来使用System.Threading.Timer来实现简单例子

System.Threading.Timer  mytimer =  new System.Threading.Timer(new  System.Threading.TimerCallback(timerCall), null, 0, 1000);///回滚执行  构造线程定时器 

public Timer(
    TimerCallback callback,   // TimerCallback 委托,表示要执行的方法。
 
    object state,           //一个包含回调方法要使用的信息的对象,或者为 null。
   
    int dueTime,    //第一次执行调用方法等待时间   // 指定零 (0) 可立即启动计时器。
                    //指定零 (-1) 表示本定时器被禁用。
                    //Change(Int32,Int32)方法可以改写定时器参数
 
    int period  // 执行间隔时间
          //如果 period 为零 (0) 或 -1 毫秒,而且dueTime 为正,则只会调用一次方法;
                //然后计时器的定时行为将被禁用,使用 Change 可以改写定时器参数。
)

目前本人就了解这么多,如有错误,有望大佬指正

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值