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

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

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

 /// <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. 我的ORM之十二 -- 支持的数据库及差别

    我的ORM索引 支持最好的是SqlServer2005,Sqlserver2008,SqlServer2012 ,后续将支持:MySql,Sqlite,Oracle. 1.分页差别 MsSql 200 ...

  2. 即时通信系统中如何实现:全局系统通知,并与Web后台集成?【低调赠送:QQ高仿版GGTalk 5.1 最新源码】

    像QQ这样的即时通信软件,时不时就会从桌面的右下角弹出一个小窗口,或是显示一个广告.或是一个新闻.或是一个公告等.在这里,我们将其统称为“全局系统通知”.很多使用GGTalk的朋友都建议我加上一个类似 ...

  3. C#中的线程二(Cotrol.BeginInvoke和Control.Invoke)

    C#中的线程二(Cotrol.BeginInvoke和Control.Invoke) 原文地址:http://www.cnblogs.com/whssunboy/archive/2007/06/07/ ...

  4. 冲刺阶段 day 9

    项目进展 昨天终于完成了教师部分的内容,今天我们又重新开始对之前系部设置不能实现的内容进行了编写,之前缺少删除和查询也做了补充,在与数据库的连接上也做了修改和更新. 存在问题 由于是之前遇到困难没做完 ...

  5. 【吉光片羽】ie6兼容性的几个点

    1.浮动换行.自己写个导航,li向左浮动,到ie6下全部错开了. --> 还是在现有bootstrap框架的基础上修改样式保险一些. <div id="mymenu" ...

  6. javascript无缝滚动示例

    效果 图片大小均为200*200; 默认向左循环滚动; 鼠标悬浮暂停,鼠标移走继续滚动; 可以在此基础进行扩展. 下面是代码: <!doctype html> <html lang= ...

  7. Java程序员的日常——SpringMVC+Mybatis开发流程、推荐系统

    今天大部分时间都在写业务代码,然后算是从无到有的配置了下spring与mybatis的集成. SpringMVC+Mybatis Web开发流程 配置数据源 在applicationContext.x ...

  8. Atitit. Atiposter 发帖机 新特性 poster new feature v11  .docx

    Atitit. Atiposter 发帖机 新特性 poster new feature v11  .docx 1.1.  版本历史1 2. 1. 未来版本规划2 2.1. V12版本规划2 2.2. ...

  9. Linux初学 - SSH

    SSH:SSH 为 Secure Shell 的缩写,由 IETF 的网络小组(Network Working Group)所制定:SSH 为建立在应用层和传输层基础上的安全协议.SSH 是目前较可靠 ...

  10. react3 组件

    <body><!-- React 真实 DOM 将会插入到这里 --><div id="example"></div> <!- ...