赞
踩
本文是学习Siki学院Plane老师的《定时回调系统技术专题》视频课程的学习笔记和总结
- using System;
- using System.Collections.Generic;
- using System.Timers;
-
- public class PETimer {
- private Action<string> taskLog;
- private Action<Action<int>, int> taskHandle;
- private static readonly string lockTid = "lockTid";
- private DateTime startDateTime = new DateTime(1970, 1, 1, 0, 0, 0, 0);
- private double nowTime;
- private Timer srvTimer;
- private int tid;
- private List<int> tidLst = new List<int>();
- private List<int> recTidLst = new List<int>();
-
- private static readonly string lockTime = "lockTime";
- private List<PETimeTask> tmpTimeLst = new List<PETimeTask>();
- private List<PETimeTask> taskTimeLst = new List<PETimeTask>();
- private List<int> tmpDelTimeLst = new List<int>();
-
- private int frameCounter;
-
- private static readonly string lockFrame = "lockFrame";
- private List<PEFrameTask> tmpFrameLst = new List<PEFrameTask>();
- private List<PEFrameTask> taskFrameLst = new List<PEFrameTask>();
- private List<int> tmpDelFrameLst = new List<int>();
-
- public PETimer(int interval = 0) {
- tidLst.Clear();
- recTidLst.Clear();
-
- tmpTimeLst.Clear();
- taskTimeLst.Clear();
-
- tmpFrameLst.Clear();
- taskFrameLst.Clear();
-
- if (interval != 0) {
- srvTimer = new Timer(interval) {
- AutoReset = true
- };
-
- srvTimer.Elapsed += (object sender, ElapsedEventArgs args) => {
- Update();
- };
- srvTimer.Start();
- }
- }
-
- public void Update() {
- CheckTimeTask();
- CheckFrameTask();
-
- DelTimeTask();
- DelFrameTask();
-
- if (recTidLst.Count > 0) {
- lock (lockTid) {
- RecycleTid();
- }
- }
- }
- private void DelTimeTask() {
- if (tmpDelTimeLst.Count > 0) {
- lock (lockTime) {
- for (int i = 0; i < tmpDelTimeLst.Count; i++) {
- bool isDel = false;
- int delTid = tmpDelTimeLst[i];
- for (int j = 0; j < taskTimeLst.Count; j++) {
- PETimeTask task = taskTimeLst[j];
- if (task.tid == delTid) {
- isDel = true;
- taskTimeLst.RemoveAt(j);
- recTidLst.Add(delTid);
- //LogInfo("Del taskTimeLst ID:" + System.Threading.Thread.CurrentThread.ManagedThreadId.ToString());
- break;
- }
- }
-
- if (isDel)
- continue;
-
- for (int j = 0; j < tmpTimeLst.Count; j++) {
- PETimeTask task = tmpTimeLst[j];
- if (task.tid == delTid) {
- tmpTimeLst.RemoveAt(j);
- recTidLst.Add(delTid);
- //LogInfo("Del tmpTimeLst ID:" + System.Threading.Thread.CurrentThread.ManagedThreadId.ToString());
- break;
- }
- }
- }
- }
- }
- }
- private void DelFrameTask() {
- if (tmpDelFrameLst.Count > 0) {
- lock (lockFrame) {
- for (int i = 0; i < tmpDelFrameLst.Count; i++) {
- bool isDel = false;
- int delTid = tmpDelFrameLst[i];
- for (int j = 0; j < taskFrameLst.Count; j++) {
- PEFrameTask task = taskFrameLst[j];
- if (task.tid == delTid) {
- isDel = true;
- taskFrameLst.RemoveAt(j);
- recTidLst.Add(delTid);
- break;
- }
- }
-
- if (isDel)
- continue;
-
- for (int j = 0; j < tmpFrameLst.Count; j++) {
- PEFrameTask task = tmpFrameLst[j];
- if (task.tid == delTid) {
- tmpFrameLst.RemoveAt(j);
- recTidLst.Add(delTid);
- break;
- }
- }
- }
- }
- }
- }
- private void CheckTimeTask() {
- if (tmpTimeLst.Count > 0) {
- lock (lockTime) {
- //加入缓存区中的定时任务
- for (int tmpIndex = 0; tmpIndex < tmpTimeLst.Count; tmpIndex++) {
- taskTimeLst.Add(tmpTimeLst[tmpIndex]);
- }
- tmpTimeLst.Clear();
- }
- }
-
- //遍历检测任务是否达到条件
- nowTime = GetUTCMilliseconds();
- for (int index = 0; index < taskTimeLst.Count; index++) {
- PETimeTask task = taskTimeLst[index];
- if (nowTime.CompareTo(task.destTime) < 0) {
- continue;
- }
- else {
- Action<int> cb = task.callback;
- try {
- if (taskHandle != null) {
- taskHandle(cb, task.tid);
- }
- else {
- if (cb != null) {
- cb(task.tid);
- }
- }
- }
- catch (Exception e) {
- LogInfo(e.ToString());
- }
-
- //移除已经完成的任务
- if (task.count == 1) {
- taskTimeLst.RemoveAt(index);
- index--;
- recTidLst.Add(task.tid);
- }
- else {
- if (task.count != 0) {
- task.count -= 1;
- }
- task.destTime += task.delay;
- }
- }
- }
- }
- private void CheckFrameTask() {
- if (tmpFrameLst.Count > 0) {
- lock (lockFrame) {
- //加入缓存区中的定时任务
- for (int tmpIndex = 0; tmpIndex < tmpFrameLst.Count; tmpIndex++) {
- taskFrameLst.Add(tmpFrameLst[tmpIndex]);
- }
- tmpFrameLst.Clear();
- }
- }
-
- frameCounter += 1;
- //遍历检测任务是否达到条件
- for (int index = 0; index < taskFrameLst.Count; index++) {
- PEFrameTask task = taskFrameLst[index];
- if (frameCounter < task.destFrame) {
- continue;
- }
- else {
- Action<int> cb = task.callback;
- try {
- if (taskHandle != null) {
- taskHandle(cb, task.tid);
- }
- else {
- if (cb != null) {
- cb(task.tid);
- }
- }
- }
- catch (Exception e) {
- LogInfo(e.ToString());
- }
-
- //移除已经完成的任务
- if (task.count == 1) {
- taskFrameLst.RemoveAt(index);
- index--;
- recTidLst.Add(task.tid);
- }
- else {
- if (task.count != 0) {
- task.count -= 1;
- }
- task.destFrame += task.delay;
- }
- }
- }
- }
-
- #region TimeTask
- public int AddTimeTask(Action<int> callback, double delay, PETimeUnit timeUnit = PETimeUnit.Millisecond, int count = 1) {
- if (timeUnit != PETimeUnit.Millisecond) {
- switch (timeUnit) {
- case PETimeUnit.Second:
- delay = delay * 1000;
- break;
- case PETimeUnit.Minute:
- delay = delay * 1000 * 60;
- break;
- case PETimeUnit.Hour:
- delay = delay * 1000 * 60 * 60;
- break;
- case PETimeUnit.Day:
- delay = delay * 1000 * 60 * 60 * 24;
- break;
- default:
- LogInfo("Add Task TimeUnit Type Error...");
- break;
- }
- }
- int tid = GetTid(); ;
- nowTime = GetUTCMilliseconds();
- lock (lockTime) {
- tmpTimeLst.Add(new PETimeTask(tid, callback, nowTime + delay, delay, count));
- }
- return tid;
- }
- public void DeleteTimeTask(int tid) {
- lock (lockTime) {
- tmpDelTimeLst.Add(tid);
- //LogInfo("TmpDel ID:" + System.Threading.Thread.CurrentThread.ManagedThreadId.ToString());
- }
- /*
- bool exist = false;
- for (int i = 0; i < taskTimeLst.Count; i++) {
- PETimeTask task = taskTimeLst[i];
- if (task.tid == tid) {
- //taskTimeLst.RemoveAt(i);
- for (int j = 0; j < tidLst.Count; j++) {
- if (tidLst[j] == tid) {
- //tidLst.RemoveAt(j);
- break;
- }
- }
- exist = true;
- break;
- }
- }
- if (!exist) {
- for (int i = 0; i < tmpTimeLst.Count; i++) {
- PETimeTask task = tmpTimeLst[i];
- if (task.tid == tid) {
- //tmpTimeLst.RemoveAt(i);
- for (int j = 0; j < tidLst.Count; j++) {
- if (tidLst[j] == tid) {
- //tidLst.RemoveAt(j);
- break;
- }
- }
- exist = true;
- break;
- }
- }
- }
- return exist;
- */
- }
- public bool ReplaceTimeTask(int tid, Action<int> callback, float delay, PETimeUnit timeUnit = PETimeUnit.Millisecond, int count = 1) {
- if (timeUnit != PETimeUnit.Millisecond) {
- switch (timeUnit) {
- case PETimeUnit.Second:
- delay = delay * 1000;
- break;
- case PETimeUnit.Minute:
- delay = delay * 1000 * 60;
- break;
- case PETimeUnit.Hour:
- delay = delay * 1000 * 60 * 60;
- break;
- case PETimeUnit.Day:
- delay = delay * 1000 * 60 * 60 * 24;
- break;
- default:
- LogInfo("Replace Task TimeUnit Type Error...");
- break;
- }
- }
- nowTime = GetUTCMilliseconds();
- PETimeTask newTask = new PETimeTask(tid, callback, nowTime + delay, delay, count);
-
- bool isRep = false;
- for (int i = 0; i < taskTimeLst.Count; i++) {
- if (taskTimeLst[i].tid == tid) {
- taskTimeLst[i] = newTask;
- isRep = true;
- break;
- }
- }
-
- if (!isRep) {
- for (int i = 0; i < tmpTimeLst.Count; i++) {
- if (tmpTimeLst[i].tid == tid) {
- tmpTimeLst[i] = newTask;
- isRep = true;
- break;
- }
- }
- }
-
- return isRep;
- }
- #endregion
-
- #region FrameTask
- public int AddFrameTask(Action<int> callback, int delay, int count = 1) {
- int tid = GetTid();
- lock (lockTime) {
- tmpFrameLst.Add(new PEFrameTask(tid, callback, frameCounter + delay, delay, count));
- }
- return tid;
- }
- public void DeleteFrameTask(int tid) {
- lock (lockFrame) {
- tmpDelFrameLst.Add(tid);
- }
- /*
- bool exist = false;
- for (int i = 0; i < taskFrameLst.Count; i++) {
- PEFrameTask task = taskFrameLst[i];
- if (task.tid == tid) {
- //taskFrameLst.RemoveAt(i);
- for (int j = 0; j < tidLst.Count; j++) {
- if (tidLst[j] == tid) {
- //tidLst.RemoveAt(j);
- break;
- }
- }
- exist = true;
- break;
- }
- }
- if (!exist) {
- for (int i = 0; i < tmpFrameLst.Count; i++) {
- PEFrameTask task = tmpFrameLst[i];
- if (task.tid == tid) {
- //tmpFrameLst.RemoveAt(i);
- for (int j = 0; j < tidLst.Count; j++) {
- if (tidLst[j] == tid) {
- //tidLst.RemoveAt(j);
- break;
- }
- }
- exist = true;
- break;
- }
- }
- }
- return exist;
- */
- }
- public bool ReplaceFrameTask(int tid, Action<int> callback, int delay, int count = 1) {
- PEFrameTask newTask = new PEFrameTask(tid, callback, frameCounter + delay, delay, count);
-
- bool isRep = false;
- for (int i = 0; i < taskFrameLst.Count; i++) {
- if (taskFrameLst[i].tid == tid) {
- taskFrameLst[i] = newTask;
- isRep = true;
- break;
- }
- }
-
- if (!isRep) {
- for (int i = 0; i < tmpFrameLst.Count; i++) {
- if (tmpFrameLst[i].tid == tid) {
- tmpFrameLst[i] = newTask;
- isRep = true;
- break;
- }
- }
- }
-
- return isRep;
- }
- #endregion
-
- public void SetLog(Action<string> log) {
- taskLog = log;
- }
-
- public void SetHandle(Action<Action<int>, int> handle) {
- taskHandle = handle;
- }
-
- public void Reset() {
- tid = 0;
- tidLst.Clear();
- recTidLst.Clear();
-
- tmpTimeLst.Clear();
- taskTimeLst.Clear();
-
- tmpFrameLst.Clear();
- taskFrameLst.Clear();
-
- taskLog = null;
- srvTimer.Stop();
- }
-
- public int GetYear() {
- return GetLocalDateTime().Year;
- }
- public int GetMonth() {
- return GetLocalDateTime().Month;
- }
- public int GetDay() {
- return GetLocalDateTime().Day;
- }
- public int GetWeek() {
- return (int)GetLocalDateTime().DayOfWeek;
- }
- public DateTime GetLocalDateTime() {
- DateTime dt = TimeZone.CurrentTimeZone.ToLocalTime(startDateTime.AddMilliseconds(nowTime));
- return dt;
- }
- public double GetMillisecondsTime() {
- return nowTime;
- }
- public string GetLocalTimeStr() {
- DateTime dt = GetLocalDateTime();
- string str = GetTimeStr(dt.Hour) + ":" + GetTimeStr(dt.Minute) + ":" + GetTimeStr(dt.Second);
- return str;
- }
-
- #region Tool Methonds
- private int GetTid() {
- lock (lockTid) {
- tid += 1;
-
- //安全代码,以防万一
- while (true) {
- if (tid == int.MaxValue) {
- tid = 0;
- }
-
- bool used = false;
- for (int i = 0; i < tidLst.Count; i++) {
- if (tid == tidLst[i]) {
- used = true;
- break;
- }
- }
- if (!used) {
- tidLst.Add(tid);
- break;
- }
- else {
- tid += 1;
- }
- }
- }
-
- return tid;
- }
- private void RecycleTid() {
- for (int i = 0; i < recTidLst.Count; i++) {
- int tid = recTidLst[i];
-
- for (int j = 0; j < tidLst.Count; j++) {
- if (tidLst[j] == tid) {
- tidLst.RemoveAt(j);
- break;
- }
- }
- }
- recTidLst.Clear();
- }
- private void LogInfo(string info) {
- if (taskLog != null) {
- taskLog(info);
- }
- }
- private double GetUTCMilliseconds() {
- TimeSpan ts = DateTime.UtcNow - startDateTime;
- return ts.TotalMilliseconds;
- }
- private string GetTimeStr(int time) {
- if (time < 10) {
- return "0" + time;
- }
- else {
- return time.ToString();
- }
- }
- #endregion
-
- class PETimeTask {
- public int tid;
- public Action<int> callback;
- public double destTime;//单位:毫秒
- public double delay;
- public int count;
-
- public PETimeTask(int tid, Action<int> callback, double destTime, double delay, int count) {
- this.tid = tid;
- this.callback = callback;
- this.destTime = destTime;
- this.delay = delay;
- this.count = count;
- }
- }
-
- class PEFrameTask {
- public int tid;
- public Action<int> callback;
- public int destFrame;
- public int delay;
- public int count;
-
- public PEFrameTask(int tid, Action<int> callback, int destFrame, int delay, int count) {
- this.tid = tid;
- this.callback = callback;
- this.destFrame = destFrame;
- this.delay = delay;
- this.count = count;
- }
- }
- }
-
- public enum PETimeUnit {
- Millisecond,
- Second,
- Minute,
- Hour,
- Day
- }

PETimer控制台工程案例代码:
- using System;
- using System.Threading;
- using System.Collections.Generic;
-
- namespace ConsoleProjects {
- class Program {
- private static readonly string obj = "lock";
-
- static void Main(string[] args) {
- Console.WriteLine("Test Start!");
- //Test1();
- Test2();
- }
-
- //第一种用法:运行线程检测并处理任务
- static void Test1() {
- //运行线程驱动计时
- PETimer pt = new PETimer();
- pt.SetLog((string info) => {
- Console.WriteLine("LogInfo:" + info);
- });
-
- pt.AddTimeTask((int tid) => {
- Console.WriteLine("Process线程ID:{0}", Thread.CurrentThread.ManagedThreadId.ToString());
- }, 10, PETimeUnit.Millisecond, 0);
-
- while (true) {
- pt.Update();
- }
- }
-
- //第二种用法:独立线程检测并处理任务
- static void Test2() {
- Queue<TaskPack> tpQue = new Queue<TaskPack>();
- //独立线程驱动计时
- PETimer pt = new PETimer(5);
- pt.SetLog((string info) => {
- Console.WriteLine("LogInfo:" + info);
- });
-
-
- int id = pt.AddTimeTask((int tid) => {
- Console.WriteLine("Process线程ID:{0}", Thread.CurrentThread.ManagedThreadId.ToString());
- }, 3000, PETimeUnit.Millisecond, 0);
-
- //设置回调处理器
- /*
- pt.SetHandle((Action<int> cb, int tid) => {
- if (cb != null) {
- lock (obj) {
- tpQue.Enqueue(new TaskPack(tid, cb));
- }
- }
- });
- */
- while (true) {
- string ipt = Console.ReadLine();
- if (ipt == "a") {
- pt.DeleteTimeTask(id);
- }
-
-
- if (tpQue.Count > 0) {
- TaskPack tp = null;
- lock (obj) {
- tp = tpQue.Dequeue();
- }
- tp.cb(tp.tid);
- }
- }
- }
- }
-
- //任务数据包
- class TaskPack {
- public int tid;
- public Action<int> cb;
- public TaskPack(int tid, Action<int> cb) {
- this.tid = tid;
- this.cb = cb;
- }
- }
- }

PETimer集成到Unity案例代码:
- using UnityEngine;
-
- public class GameStart : MonoBehaviour {
- PETimer pt = new PETimer();
-
- int tempID = -1;
- private void Start() {
- //时间定时
- pt.AddTimeTask(TimerTask, 500, PETimeUnit.Millisecond, 3);
- //帧数定时
- pt.AddFrameTask(FrameTask, 100, 3);
-
- //定时替换/删除
- tempID = pt.AddTimeTask((int tid) => {
- Debug.Log("定时等待替换......");
- }, 1, PETimeUnit.Second, 0);
- }
-
- private void Update() {
- pt.Update();
-
- //定时替换
- if (Input.GetKeyDown(KeyCode.R)) {
-
- bool succ = pt.ReplaceTimeTask(tempID, (int tid) => {
- Debug.Log("定时等待删除......");
- }, 2, PETimeUnit.Second, 0);
-
- if (succ) {
- Debug.Log("替换成功");
- }
- }
-
- //定时删除
- if (Input.GetKeyDown(KeyCode.D)) {
- pt.DeleteTimeTask(tempID);
- }
- }
-
- void TimerTask(int tid) {
- Debug.Log("TimeTask:" + System.DateTime.UtcNow);
- }
-
- void FrameTask(int tid) {
- Debug.Log("FrameTask:" + System.DateTime.UtcNow);
- }
- }

Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。