计时服务-计时器(Client)

//==========================
// - FileName:      PETimer.cs         
// - Created:       true.	
// - CreateTime:    2020/08/07 02:40:30	
// - Email:         1670328571@qq.com		
// - Region:        China WUHAN	
// - Description:   计时器
//==========================
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
}
//==========================
// - FileName:      TimerSvc.cs         
// - Created:       true.	
// - CreateTime:    2020/08/24 02:47:57	
// - Email:         1670328571@qq.com		
// - Region:        China WUHAN	
// - Description:   计时服务
//==========================
using System;

public class TimerSvc : SystemRoot
{
    public static TimerSvc Instance = null;
    private PETimer pt;

    public void InitSvc()
    {
        Instance = this;
        pt = new PETimer();
        //设置日志输出    
        pt.SetLog((string info) =>
        {
            PECommon.Log(info);
        });
        PECommon.Log("Init TimerSvc...");
    }


    public void Update()
    {
        pt.Update();
    }

    public int AddTimeTask(Action<int> callback, double delay, PETimeUnit timeUnit = PETimeUnit.Millisecond, int count = 1)
    {
        return pt.AddTimeTask(callback, delay, timeUnit, count);
    }
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值