上一篇文章我们讲诉了自定义线程执行器和任务处理器

我们继续来讲解自定义线程的定时执行器,我们在很多场景下需要做到某些状态或者数据进行更新,如果事情很多很杂,很时候时候会创建很多不同的定时器那么势必会照成系统的消耗和性能低下的问题!今天我们来解决这一问题。

首先我们创建定时任务执行器基类

 /// <summary>
     ///
     /// </summary>
     public abstract class TimerTaskBase : BaseTask
     {

         /// <summary>
         /// 开始执行的时间
         /// </summary>
         public long StartTime { get; set; }

         /// <summary>
         /// 是否一开始执行一次
         /// </summary>
         public bool IsStartAction { get; set; }

         /// <summary>
         /// 结束时间
         /// </summary>
         public long EndTime { get; set; }

         /// <summary>
         /// 执行次数
         /// </summary>
         public int ActionCount { get; set; }

         /// <summary>
         /// 已经执行的次数
         /// </summary>
         public int AActionCount { get; set; }

         /// <summary>
         /// 间隔执行时间
         /// </summary>
         public int IntervalTime { get; set; }

         /// <summary>
         /// 制定执行次数的定时任务
         /// </summary>
         /// <param name="startTime">0表示立即执行,否则延迟执行,填写开始时间</param>
         /// <param name="intervalTime">执行间隔时间,小于10毫秒,当10毫秒处理</param>
         /// <param name="isStartAction">是否一开始执行一次</param>
         /// <param name="actionCount">需要执行的次数</param>
         public TimerTaskBase(long startTime, int intervalTime, bool isStartAction, int actionCount)
         {
             this.StartTime = startTime;
             this.IntervalTime = intervalTime;
             this.IsStartAction = isStartAction;
             this.ActionCount = actionCount;
             ;
         }

         /// <summary>
         /// 制定结束时间的定时任务
         /// </summary>
         /// <param name="startTime">0表示立即执行,否则延迟执行,填写开始时间</param>
         /// <param name="intervalTime">执行间隔时间,小于10毫秒,当10毫秒处理</param>
         /// <param name="endTime">执行结束时间</param>
         /// <param name="isStartAction">是否一开始执行一次</param>
         public TimerTaskBase(long startTime, int intervalTime, long endTime, bool isStartAction)
         {
             this.StartTime = startTime;
             this.IntervalTime = intervalTime;
             this.IsStartAction = isStartAction;
             ;
             this.EndTime = endTime;
         }

         /// <summary>
         /// 制定开始时间,无限执行任务
         /// </summary>
         /// <param name="startTime">0表示立即执行,否则延迟执行,填写开始时间</param>
         /// <param name="intervalTime">执行间隔时间,小于10毫秒,当 10 毫秒处理 建议 10 毫秒的倍数</param>
         /// <param name="isStartAction">是否一开始执行一次</param>
         public TimerTaskBase(long startTime, int intervalTime, bool isStartAction)
         {
             this.StartTime = startTime;
             this.IntervalTime = intervalTime;
             this.IsStartAction = isStartAction;
             ;
             ;
         }

         public TimerTaskBase()
         {
             // TODO: Complete member initialization
         }
     }

上面的代码实现了,开始时间,间隔时间,结束时间和执行次数 的控制

那么我们来看看定时器线程的设计

 public class TimerThread
     {
         public TimerThread()
         {
             System.Threading.Thread thread = new System.Threading.Thread(new System.Threading.ThreadStart(Run));
             thread.IsBackground = true;
             thread.Start();
         }

         /// <summary>
         /// 任务队列
         /// </summary>
         private List<TimerTaskBase> taskQueue = new List<TimerTaskBase>();

         /// <summary>
         /// 加入任务
         /// </summary>
         /// <param name="t"></param>
         public void AddTask(TimerTaskBase t)
         {
             if (t.IsStartAction)
             {
                 //满足添加队列前先执行一次
                 t.Run();
             }
             lock (taskQueue)
             {
                 taskQueue.Add(t);
             }
         }

         public long GetDate()
         {
             return Convert.ToInt64(System.DateTime.Now.ToString("yyyyMMddHHmmssfff"));
         }

         //这里的线程同步器,不是用来通知的,
         //只是用来暂停的,因为Thread.Sleep() 消耗开销比较大
         ManualResetEvent mre = new ManualResetEvent(false);

         /// <summary>
         /// 重构函数执行器
         /// </summary>
         private void Run()
         {
             ///无限循环执行函数器
             while (true)
             {
                 )
                 {
                     IEnumerable<TimerTaskBase> collections = null;
                     lock (taskQueue)
                     {
                         //拷贝一次队列 预防本次轮训检查的时候有新的任务添加
                         //否则循环会出错 集合被修改无法迭代
                         collections = new List<TimerTaskBase>(taskQueue);
                     }
                     //开始迭代
                     foreach (TimerTaskBase tet in collections)
                     {
                         int actionCount = tet.AActionCount;
                         long timers = GetDate();
                          && timers > tet.EndTime) || (tet.ActionCount >  && actionCount >= tet.ActionCount))
                         {
                             //任务过期
                             lock (taskQueue)
                             {
                                 taskQueue.Remove(tet);
                             }
                             continue;
                         }
                         //获取最后一次的执行时间
                         long lastactiontime = tet.TempAttribute.getlongValue("lastactiontime");
                          && Math.Abs(timers - lastactiontime) < tet.IntervalTime)
                         {
                             continue;
                         }
                         //记录出来次数
                         tet.AActionCount++;
                         //记录最后执行的时间
                         tet.TempAttribute.setValue("lastactiontime", timers);

                         //上面的代码执行情况是非常几乎不用考虑消耗问题

                         //下面是任务的执行需要考虑消耗,

                         //这里我们不考虑执行耗时问题,
                         //我们我这里没有涉及到后台线程池
                         //也没有具体的业务逻辑,所以都放到这里统一执行
                         tet.Run();
                     }
                 }
                 //暂停10毫秒后再次检查
                 mre.WaitOne();
             }
         }
     }

定时器为什么没有使用上一篇文章讲诉的自定义线程呢,是因为,上一篇文章的自定义线程是基于队列处理的,先进先出执行,而我们的定时器任务并非是基于队列的。所以需要单独定义。

那么我们先来实现一个每一秒执行的任务,

  /// <summary>
     /// 每秒执行的任务
     /// </summary>
     public class SecondsTimerTask : TimerTaskBase
     {
         /// <summary>
         /// 定义一秒执行一次的
         /// </summary>
         public SecondsTimerTask()
             : , , false)
         {

         }

         public override void Run()
         {
             Console.WriteLine(DateTime.Now.ToString("HH:mm:ss:ffff: ") + "我是 每秒 执行的任务");
         }
     }

我们来测试一下看看效果

     class Program
     {
         static void Main(string[] args)
         {
             TimerThread timerThread = new TimerThread();
             timerThread.AddTask(new SecondsTimerTask());
             Console.ReadLine();
         }
     }

还算是我们的预想的效果吧,每秒执行一次

接下来我们创建每分钟执行一次

     public class MinuteTimerTask : TimerTaskBase
     {
         /// <summary>
         /// 定义一分钟执行一次的
         /// </summary>
         public MinuteTimerTask()
             : ,  * , false)
         {

         }

         public override void Run()
         {
             Console.WriteLine(DateTime.Now.ToString("HH:mm:ss:ffff: ") + "我是 每分钟 执行的任务");
         }
     }

按照执行次数的定时器

     /// <summary>
     /// 我是按照执行次数结束的
     /// </summary>
     public class CountTimerTask : TimerTaskBase
     {
         /// <summary>
         /// 定义一秒执行一次的
         /// </summary>
         public CountTimerTask()
             : , , )
         {

         }

         public override void Run()
         {
             Console.WriteLine(DateTime.Now.ToString("HH:mm:ss:ffff: ") + "我是 次数 执行的任务 我要执行:" + this.ActionCount + " 次 执行了: " + this.AActionCount + " 次");
         }
     }

测试一下

    class Program
     {
         static void Main(string[] args)
         {
             TimerThread timerThread = new TimerThread();
             timerThread.AddTask(new SecondsTimerTask());

             timerThread.AddTask(new MinuteTimerTask());
             timerThread.AddTask(new CountTimerTask());

             Console.ReadLine();
         }
     }

运行结果:

到此我们的定时器线程执行器已经完成,满足我们需要做到定时更新状态,合作检查数据等应用场景!

不知道对你有没有帮助呢?

请不了吝啬你的小手,给予一个评论吧,帮助到你了请给与鼓励,如果有不足之处还请多多指教!

C# 线程系列三 定时器线程的更多相关文章

  1. 线程系列08,实现线程锁的各种方式,使用lock,Montor,Mutex,Semaphore以及线程死锁

    当涉及到多线程共享数据,需要数据同步的时候,就可以考虑使用线程锁了.本篇体验线程锁的各种用法以及线程死锁.主要包括: ※ 使用lock处理数据同步※ 使用Monitor.Enter和Monitor.E ...

  2. 【java线程系列】java线程系列之java线程池详解

    一线程池的概念及为何需要线程池: 我们知道当我们自己创建一个线程时如果该线程执行完任务后就进入死亡状态,这样如果我们需要在次使用一个线程时得重新创建一个线程,但是线程的创建是要付出一定的代价的,如果在 ...

  3. 【java线程系列】java线程系列之线程间的交互wait()/notify()/notifyAll()及生产者与消费者模型

    关于线程,博主写过java线程详解基本上把java线程的基础知识都讲解到位了,但是那还远远不够,多线程的存在就是为了让多个线程去协作来完成某一具体任务,比如生产者与消费者模型,因此了解线程间的协作是非 ...

  4. pThreads线程(三) 线程同步--条件变量

    条件变量(Condition Variables) 参考资料:http://game-lab.org/posts/posix-thread-cn/#5.1 条件变量是什么? 条件变量为我们提供了另一种 ...

  5. java线程系列之三(线程协作)

    本文来自:高爽|Coder,原文地址:http://blog.csdn.net/ghsau/article/details/7433673,转载请注明. 上一篇讲述了线程的互斥(同步),但是在很多情况 ...

  6. java多线程与线程并发三:线程同步通信

    本文章内容整理自:张孝祥_Java多线程与并发库高级应用视频教程. 有些时候,线程间需要传递消息,比如下面这道面试题: 子线程循环10次,然后主线程循环100次,然后又回到子线程循环50次,然后再回到 ...

  7. Java多线程系列三——实现线程同步的方法

    两种实现线程同步的方法 方法 特性 synchronized 不需要显式地加解锁,易实现 ReentrantLock 需要显式地加解锁,灵活性更好,性能更优秀,结合Condition可实现多种条件锁 ...

  8. (Java多线程系列三)线程间通讯

    Java多线程间通讯 多线程之间通讯,其实就是多个线程在操作同一个资源,但是操作的动作不同. 1.使用wait()和notify()方法在线程中通讯 需求:第一个线程写入(input)用户,另一个线程 ...

  9. 死磕 java线程系列之创建线程的8种方式

    (手机横屏看源码更方便) 问题 (1)创建线程有哪几种方式? (2)它们分别有什么运用场景? 简介 创建线程,是多线程编程中最基本的操作,彤哥总结了一下,大概有8种创建线程的方式,你知道吗? 继承Th ...

随机推荐

  1. Caused by: java.lang.UnsatisfiedLinkError...解决经历

    Caused by: java.lang.UnsatisfiedLinkError: Couldn't load BaiduMapVOS_v2_1_3: findLibrary returned nu ...

  2. 【推荐】【给中高级开发者】构建高性能ASP.NET应用的几点建议

    本篇目录 早期阶段就要对应用进行负载测试 使用高性能类库 你的应用是CPU密集还是IO密集的 使用基于Task的异步模型,但要慎重 分发缓存和会话(session)状态 创建Web Gardens 巧 ...

  3. 如何自行处理写好的eclipse插件安装不生效

    本帖最后由 anrainie 于 2013-7-23 11:31 编辑 对于eclipse插件开发的新手,经常会遇到插件写好了,拷贝到plugins或dropins文件下,但是没有生效.上网各种问,也 ...

  4. 前端自动化测试工具doh学习总结(一)

    前言 项目中需要用到前端自动化测试,自己被当作一个探针研究了下目前用的比较多的web自动化测试工具.一开始研究的是的selenium,但由于项目使用了大量的dijit控件,写起testCase来很费劲 ...

  5. python的高性能web应用的开发与测试实验

    python的高性能web应用的开发与测试实验 tornado“同步和异步”网络IO模型实验 引言 python语言一直以开发效率高著称,被广泛地应用于自动化领域: 测试自动化 运维自动化 构建发布自 ...

  6. jQuery同步Ajax带来的UI线程阻塞问题及解决办法

    俗话说不作死就不会死,今天作死了一回,写了一个比较二逼的函数,遇到了同步Ajax引起的UI线程阻塞问题,在此记录一下. 事情起因是这样的,因为页面上有多个相似的异步请求动作,本着提高代码可重用性的原则 ...

  7. Senparc.Weixin.MP SDK 微信公众平台开发教程(十):多客服接口说明

    微信官方的多客服接口原理是通过用户发送的信息,开发者服务器返回一条指定类型的响应信息,使用户的对话状态切换到官方的多客服状态(持续一段时间),这段时间内用户发送的所有信息都不会到达开发者的服务器,而是 ...

  8. webservice5

    如何访问webservice . 三种方式我知道, 但是, 方式1 只说明了如何访问wsdl, 不知道如何调用,现在就是需要知道如何像下面url描述一样 , http get .post 方式调用ws ...

  9. 爱上MVC~为CheckBoxFor和RadioButtonFor加个扩展方法吧(希望MVC5把这方法收纳——呵呵)

    回到目录 说在前 我都是喜欢把问题复杂化,还有总是喜欢把问题简单化,偷懒化,这也需就是一个程序员的追求吧,呵呵. 我不太喜欢重复的东西,当你看到页面上有一个以上相同的代码时,那可以说,你的代码有重构的 ...

  10. Redis的介绍及使用实例.

    本文就来讲一下Redis安装的方法和Redis生成主键的优点以及和其他几种方式生成主键的对比. 1,Redis安装首先将Redis的tar包拷贝到Linux下的根目录 然后解压到redis文件夹下:( ...