{"id":27,"date":"2019-09-09T20:52:24","date_gmt":"2019-09-09T12:52:24","guid":{"rendered":"http:\/\/www.blinkedu.cn\/?p=27"},"modified":"2019-09-09T20:55:32","modified_gmt":"2019-09-09T12:55:32","slug":"petimer","status":"publish","type":"post","link":"https:\/\/www.blinkedu.cn\/index.php\/2019\/09\/09\/petimer\/","title":{"rendered":"Unity\uff1a\u57fa\u4e8eC#\u7684\u5b9a\u65f6\u56de\u8c03\u7cfb\u7edf(\u53ef\u7528\u4e8e\u5ba2\u6237\u7aef\u548c\u670d\u52a1\u7aef)"},"content":{"rendered":"<p>\n    \u672c\u6587\u662f\u5b66\u4e60Siki\u5b66\u9662Plane\u8001\u5e08\u7684<a href=\"http:\/\/www.sikiedu.com\/course\/370\" target=\"_blank\"  rel=\"nofollow\" >\u300a\u5b9a\u65f6\u56de\u8c03\u7cfb\u7edf\u6280\u672f\u4e13\u9898\u300b<\/a>\u89c6\u9891\u8bfe\u7a0b\u7684\u5b66\u4e60\u7b14\u8bb0\u548c\u603b\u7ed3\n<\/p>\n<h3>\n    \u5b9e\u73b0\u529f\u80fd<br \/>\n<\/h3>\n<ol>\n<li>\n<p><strong>\u652f\u6301\u65f6\u95f4\u5b9a\u65f6\uff0c\u5e27\u5b9a\u65f6<\/strong>\n    <\/li>\n<li>\n<p><strong>\u652f\u6301\u4efb\u52a1\u53ef\u5faa\u73af\uff0c\u53ef\u53d6\u6d88\uff0c\u53ef\u66ff\u6362<\/strong>\n    <\/li>\n<li>\n<p><strong>\u4f7f\u7528\u7b80\u5355\uff0c\u8c03\u7528\u65b9\u4fbf<\/strong>\n    <\/li>\n<\/ol>\n<h3>\n    \u601d\u8def\uff1a<br \/>\n<\/h3>\n<ul>\n<li>\n<p><strong>\u5982\u4f55\u6269\u5c55\u5b9a\u65f6\u4efb\u52a1<\/strong>\uff1a\u5c06\u65f6\u95f4\u8ba1\u65f6\u8f6c\u4e3a\u5e27\u6570\u8ba1\u65f6\n    <\/li>\n<li>\n<p><strong>\u5982\u4f55\u6269\u5c55\u53d6\u6d88\/\u66ff\u6362\u5b9a\u65f6\u4efb\u52a1<\/strong>\uff1a\u751f\u6210\u552f\u4e00id,\u901a\u8fc7id\u7d22\u5f15\u64cd\u4f5c\u4efb\u52a1\n    <\/li>\n<li>\n<p><strong>\u5982\u4f55\u6269\u5c55\u5faa\u73af\u5b9a\u65f6\u4efb\u52a1<\/strong>\uff1a\u901a\u8fc7\u4efb\u52a1\u8ba1\u6570\u8fd0\u7b97\n    <\/li>\n<li>\n<p><strong>\u5982\u4f55\u6269\u5c55\u65f6\u95f4\u5355\u4f4d\u652f\u6301<\/strong>\uff1a\u7edf\u4e00\u6362\u7b97\u4e3a\u6700\u5c0f\u7684\u6beb\u79d2\u8fd0\u7b97\n    <\/li>\n<li>\n<p><strong>\u5982\u4f55\u652f\u6301\u591a\u7ebf\u7a0b\u5b9a\u65f6\u4efb\u52a1<\/strong>\uff1a\u901a\u8fc7\u4e34\u65f6\u5217\u8868\u8fdb\u884c\u7f13\u5b58\uff0c\u9519\u5f00\u64cd\u4f5c\u65f6\u95f4\uff1b\u907f\u514d\u4f7f\u7528\u9501\uff0c\u63d0\u5347\u64cd\u4f5c\u6548\u7387\n    <\/li>\n<li>\n<p><strong>\u5982\u4f55\u5b9e\u73b0\u57fa\u7840\u5b9a\u65f6\u4efb\u52a1<\/strong>\uff1a\u901a\u8fc7Update()\u6765\u68c0\u6d4b\u4efb\u52a1\u6761\u4ef6\n    <\/li>\n<\/ul>\n<h3>\n    \u00a0\u9700\u8981\u6ce8\u610f\u7684\u95ee\u9898\uff1a<br \/>\n<\/h3>\n<ul>\n<li>\n        \u591a\u7ebf\u7a0b\u4e2d\u7684\u7ebf\u7a0b\u6570\u636e\u5b89\u5168\u95ee\u9898\n    <\/li>\n<\/ul>\n<h3>\n    \u00a0\u6838\u5fc3\u4ee3\u7801\uff1a<br \/>\n<\/h3>\n<\/p>\n<pre class=\"prettyprint lang-cs\">using System;\nusing System.Collections.Generic;\nusing System.Timers;\n\npublic class PETimer {\n    private Action<string> taskLog;\n    private Action<Action<int>, int> taskHandle;\n    private static readonly string lockTid = \"lockTid\";\n    private DateTime startDateTime = new DateTime(1970, 1, 1, 0, 0, 0, 0);\n    private double nowTime;\n    private Timer srvTimer;\n    private int tid;\n    private List<int> tidLst = new List<int>();\n    private List<int> recTidLst = new List<int>();\n\n    private static readonly string lockTime = \"lockTime\";\n    private List<PETimeTask> tmpTimeLst = new List<PETimeTask>();\n    private List<PETimeTask> taskTimeLst = new List<PETimeTask>();\n    private List<int> tmpDelTimeLst = new List<int>();\n\n    private int frameCounter;\n\n    private static readonly string lockFrame = \"lockFrame\";\n    private List<PEFrameTask> tmpFrameLst = new List<PEFrameTask>();\n    private List<PEFrameTask> taskFrameLst = new List<PEFrameTask>();\n    private List<int> tmpDelFrameLst = new List<int>();\n\n    public PETimer(int interval = 0) {\n        tidLst.Clear();\n        recTidLst.Clear();\n\n        tmpTimeLst.Clear();\n        taskTimeLst.Clear();\n\n        tmpFrameLst.Clear();\n        taskFrameLst.Clear();\n\n        if (interval != 0) {\n            srvTimer = new Timer(interval) {\n                AutoReset = true\n            };\n\n            srvTimer.Elapsed += (object sender, ElapsedEventArgs args) => {\n                Update();\n            };\n            srvTimer.Start();\n        }\n    }\n\n    public void Update() {\n        CheckTimeTask();\n        CheckFrameTask();\n\n        DelTimeTask();\n        DelFrameTask();\n\n        if (recTidLst.Count > 0) {\n            lock (lockTid) {\n                RecycleTid();\n            }\n        }\n    }\n    private void DelTimeTask() {\n        if (tmpDelTimeLst.Count > 0) {\n            lock (lockTime) {\n                for (int i = 0; i < tmpDelTimeLst.Count; i++) {\n                    bool isDel = false;\n                    int delTid = tmpDelTimeLst[i];\n                    for (int j = 0; j < taskTimeLst.Count; j++) {\n                        PETimeTask task = taskTimeLst[j];\n                        if (task.tid == delTid) {\n                            isDel = true;\n                            taskTimeLst.RemoveAt(j);\n                            recTidLst.Add(delTid);\n                            \/\/LogInfo(\"Del taskTimeLst ID:\" + System.Threading.Thread.CurrentThread.ManagedThreadId.ToString());\n                            break;\n                        }\n                    }\n\n                    if (isDel)\n                        continue;\n\n                    for (int j = 0; j < tmpTimeLst.Count; j++) {\n                        PETimeTask task = tmpTimeLst[j];\n                        if (task.tid == delTid) {\n                            tmpTimeLst.RemoveAt(j);\n                            recTidLst.Add(delTid);\n                            \/\/LogInfo(\"Del tmpTimeLst ID:\" + System.Threading.Thread.CurrentThread.ManagedThreadId.ToString());\n                            break;\n                        }\n                    }\n                }\n            }\n        }\n    }\n    private void DelFrameTask() {\n        if (tmpDelFrameLst.Count > 0) {\n            lock (lockFrame) {\n                for (int i = 0; i < tmpDelFrameLst.Count; i++) {\n                    bool isDel = false;\n                    int delTid = tmpDelFrameLst[i];\n                    for (int j = 0; j < taskFrameLst.Count; j++) {\n                        PEFrameTask task = taskFrameLst[j];\n                        if (task.tid == delTid) {\n                            isDel = true;\n                            taskFrameLst.RemoveAt(j);\n                            recTidLst.Add(delTid);\n                            break;\n                        }\n                    }\n\n                    if (isDel)\n                        continue;\n\n                    for (int j = 0; j < tmpFrameLst.Count; j++) {\n                        PEFrameTask task = tmpFrameLst[j];\n                        if (task.tid == delTid) {\n                            tmpFrameLst.RemoveAt(j);\n                            recTidLst.Add(delTid);\n                            break;\n                        }\n                    }\n                }\n            }\n        }\n    }\n    private void CheckTimeTask() {\n        if (tmpTimeLst.Count > 0) {\n            lock (lockTime) {\n                \/\/\u52a0\u5165\u7f13\u5b58\u533a\u4e2d\u7684\u5b9a\u65f6\u4efb\u52a1\n                for (int tmpIndex = 0; tmpIndex < tmpTimeLst.Count; tmpIndex++) {\n                    taskTimeLst.Add(tmpTimeLst[tmpIndex]);\n                }\n                tmpTimeLst.Clear();\n            }\n        }\n\n        \/\/\u904d\u5386\u68c0\u6d4b\u4efb\u52a1\u662f\u5426\u8fbe\u5230\u6761\u4ef6\n        nowTime = GetUTCMilliseconds();\n        for (int index = 0; index < taskTimeLst.Count; index++) {\n            PETimeTask task = taskTimeLst[index];\n            if (nowTime.CompareTo(task.destTime) < 0) {\n                continue;\n            }\n            else {\n                Action<int> cb = task.callback;\n                try {\n                    if (taskHandle != null) {\n                        taskHandle(cb, task.tid);\n                    }\n                    else {\n                        if (cb != null) {\n                            cb(task.tid);\n                        }\n                    }\n                }\n                catch (Exception e) {\n                    LogInfo(e.ToString());\n                }\n\n                \/\/\u79fb\u9664\u5df2\u7ecf\u5b8c\u6210\u7684\u4efb\u52a1\n                if (task.count == 1) {\n                    taskTimeLst.RemoveAt(index);\n                    index--;\n                    recTidLst.Add(task.tid);\n                }\n                else {\n                    if (task.count != 0) {\n                        task.count -= 1;\n                    }\n                    task.destTime += task.delay;\n                }\n            }\n        }\n    }\n    private void CheckFrameTask() {\n        if (tmpFrameLst.Count > 0) {\n            lock (lockFrame) {\n                \/\/\u52a0\u5165\u7f13\u5b58\u533a\u4e2d\u7684\u5b9a\u65f6\u4efb\u52a1\n                for (int tmpIndex = 0; tmpIndex < tmpFrameLst.Count; tmpIndex++) {\n                    taskFrameLst.Add(tmpFrameLst[tmpIndex]);\n                }\n                tmpFrameLst.Clear();\n            }\n        }\n\n        frameCounter += 1;\n        \/\/\u904d\u5386\u68c0\u6d4b\u4efb\u52a1\u662f\u5426\u8fbe\u5230\u6761\u4ef6\n        for (int index = 0; index < taskFrameLst.Count; index++) {\n            PEFrameTask task = taskFrameLst[index];\n            if (frameCounter < task.destFrame) {\n                continue;\n            }\n            else {\n                Action<int> cb = task.callback;\n                try {\n                    if (taskHandle != null) {\n                        taskHandle(cb, task.tid);\n                    }\n                    else {\n                        if (cb != null) {\n                            cb(task.tid);\n                        }\n                    }\n                }\n                catch (Exception e) {\n                    LogInfo(e.ToString());\n                }\n\n                \/\/\u79fb\u9664\u5df2\u7ecf\u5b8c\u6210\u7684\u4efb\u52a1\n                if (task.count == 1) {\n                    taskFrameLst.RemoveAt(index);\n                    index--;\n                    recTidLst.Add(task.tid);\n                }\n                else {\n                    if (task.count != 0) {\n                        task.count -= 1;\n                    }\n                    task.destFrame += task.delay;\n                }\n            }\n        }\n    }\n\n    #region TimeTask\n    public int AddTimeTask(Action<int> callback, double delay, PETimeUnit timeUnit = PETimeUnit.Millisecond, int count = 1) {\n        if (timeUnit != PETimeUnit.Millisecond) {\n            switch (timeUnit) {\n                case PETimeUnit.Second:\n                    delay = delay * 1000;\n                    break;\n                case PETimeUnit.Minute:\n                    delay = delay * 1000 * 60;\n                    break;\n                case PETimeUnit.Hour:\n                    delay = delay * 1000 * 60 * 60;\n                    break;\n                case PETimeUnit.Day:\n                    delay = delay * 1000 * 60 * 60 * 24;\n                    break;\n                default:\n                    LogInfo(\"Add Task TimeUnit Type Error...\");\n                    break;\n            }\n        }\n        int tid = GetTid(); ;\n        nowTime = GetUTCMilliseconds();\n        lock (lockTime) {\n            tmpTimeLst.Add(new PETimeTask(tid, callback, nowTime + delay, delay, count));\n        }\n        return tid;\n    }\n    public void DeleteTimeTask(int tid) {\n        lock (lockTime) {\n            tmpDelTimeLst.Add(tid);\n            \/\/LogInfo(\"TmpDel ID:\" + System.Threading.Thread.CurrentThread.ManagedThreadId.ToString());\n        }\n        \/*\n         bool exist = false;\n\n         for (int i = 0; i < taskTimeLst.Count; i++) {\n             PETimeTask task = taskTimeLst[i];\n             if (task.tid == tid) {\n                 \/\/taskTimeLst.RemoveAt(i);\n                 for (int j = 0; j < tidLst.Count; j++) {\n                     if (tidLst[j] == tid) {\n                         \/\/tidLst.RemoveAt(j);\n                         break;\n                     }\n                 }\n                 exist = true;\n                 break;\n             }\n         }\n\n         if (!exist) {\n             for (int i = 0; i < tmpTimeLst.Count; i++) {\n                 PETimeTask task = tmpTimeLst[i];\n                 if (task.tid == tid) {\n                     \/\/tmpTimeLst.RemoveAt(i);\n                     for (int j = 0; j < tidLst.Count; j++) {\n                         if (tidLst[j] == tid) {\n                             \/\/tidLst.RemoveAt(j);\n                             break;\n                         }\n                     }\n                     exist = true;\n                     break;\n                 }\n             }\n         }\n\n         return exist;\n         *\/\n    }\n    public bool ReplaceTimeTask(int tid, Action<int> callback, float delay, PETimeUnit timeUnit = PETimeUnit.Millisecond, int count = 1) {\n        if (timeUnit != PETimeUnit.Millisecond) {\n            switch (timeUnit) {\n                case PETimeUnit.Second:\n                    delay = delay * 1000;\n                    break;\n                case PETimeUnit.Minute:\n                    delay = delay * 1000 * 60;\n                    break;\n                case PETimeUnit.Hour:\n                    delay = delay * 1000 * 60 * 60;\n                    break;\n                case PETimeUnit.Day:\n                    delay = delay * 1000 * 60 * 60 * 24;\n                    break;\n                default:\n                    LogInfo(\"Replace Task TimeUnit Type Error...\");\n                    break;\n            }\n        }\n        nowTime = GetUTCMilliseconds();\n        PETimeTask newTask = new PETimeTask(tid, callback, nowTime + delay, delay, count);\n\n        bool isRep = false;\n        for (int i = 0; i < taskTimeLst.Count; i++) {\n            if (taskTimeLst[i].tid == tid) {\n                taskTimeLst[i] = newTask;\n                isRep = true;\n                break;\n            }\n        }\n\n        if (!isRep) {\n            for (int i = 0; i < tmpTimeLst.Count; i++) {\n                if (tmpTimeLst[i].tid == tid) {\n                    tmpTimeLst[i] = newTask;\n                    isRep = true;\n                    break;\n                }\n            }\n        }\n\n        return isRep;\n    }\n    #endregion\n\n    #region FrameTask\n    public int AddFrameTask(Action<int> callback, int delay, int count = 1) {\n        int tid = GetTid();\n        lock (lockTime) {\n            tmpFrameLst.Add(new PEFrameTask(tid, callback, frameCounter + delay, delay, count));\n        }\n        return tid;\n    }\n    public void DeleteFrameTask(int tid) {\n        lock (lockFrame) {\n            tmpDelFrameLst.Add(tid);\n        }\n        \/*\n        bool exist = false;\n\n        for (int i = 0; i < taskFrameLst.Count; i++) {\n            PEFrameTask task = taskFrameLst[i];\n            if (task.tid == tid) {\n                \/\/taskFrameLst.RemoveAt(i);\n                for (int j = 0; j < tidLst.Count; j++) {\n                    if (tidLst[j] == tid) {\n                        \/\/tidLst.RemoveAt(j);\n                        break;\n                    }\n                }\n                exist = true;\n                break;\n            }\n        }\n\n        if (!exist) {\n            for (int i = 0; i < tmpFrameLst.Count; i++) {\n                PEFrameTask task = tmpFrameLst[i];\n                if (task.tid == tid) {\n                    \/\/tmpFrameLst.RemoveAt(i);\n                    for (int j = 0; j < tidLst.Count; j++) {\n                        if (tidLst[j] == tid) {\n                            \/\/tidLst.RemoveAt(j);\n                            break;\n                        }\n                    }\n                    exist = true;\n                    break;\n                }\n            }\n        }\n\n        return exist;\n        *\/\n    }\n    public bool ReplaceFrameTask(int tid, Action<int> callback, int delay, int count = 1) {\n        PEFrameTask newTask = new PEFrameTask(tid, callback, frameCounter + delay, delay, count);\n\n        bool isRep = false;\n        for (int i = 0; i < taskFrameLst.Count; i++) {\n            if (taskFrameLst[i].tid == tid) {\n                taskFrameLst[i] = newTask;\n                isRep = true;\n                break;\n            }\n        }\n\n        if (!isRep) {\n            for (int i = 0; i < tmpFrameLst.Count; i++) {\n                if (tmpFrameLst[i].tid == tid) {\n                    tmpFrameLst[i] = newTask;\n                    isRep = true;\n                    break;\n                }\n            }\n        }\n\n        return isRep;\n    }\n    #endregion\n\n    public void SetLog(Action<string> log) {\n        taskLog = log;\n    }\n\n    public void SetHandle(Action<Action<int>, int> handle) {\n        taskHandle = handle;\n    }\n\n    public void Reset() {\n        tid = 0;\n        tidLst.Clear();\n        recTidLst.Clear();\n\n        tmpTimeLst.Clear();\n        taskTimeLst.Clear();\n\n        tmpFrameLst.Clear();\n        taskFrameLst.Clear();\n\n        taskLog = null;\n        srvTimer.Stop();\n    }\n\n    public int GetYear() {\n        return GetLocalDateTime().Year;\n    }\n    public int GetMonth() {\n        return GetLocalDateTime().Month;\n    }\n    public int GetDay() {\n        return GetLocalDateTime().Day;\n    }\n    public int GetWeek() {\n        return (int)GetLocalDateTime().DayOfWeek;\n    }\n    public DateTime GetLocalDateTime() {\n        DateTime dt = TimeZone.CurrentTimeZone.ToLocalTime(startDateTime.AddMilliseconds(nowTime));\n        return dt;\n    }\n    public double GetMillisecondsTime() {\n        return nowTime;\n    }\n    public string GetLocalTimeStr() {\n        DateTime dt = GetLocalDateTime();\n        string str = GetTimeStr(dt.Hour) + \":\" + GetTimeStr(dt.Minute) + \":\" + GetTimeStr(dt.Second);\n        return str;\n    }\n\n    #region Tool Methonds\n    private int GetTid() {\n        lock (lockTid) {\n            tid += 1;\n\n            \/\/\u5b89\u5168\u4ee3\u7801\uff0c\u4ee5\u9632\u4e07\u4e00\n            while (true) {\n                if (tid == int.MaxValue) {\n                    tid = 0;\n                }\n\n                bool used = false;\n                for (int i = 0; i < tidLst.Count; i++) {\n                    if (tid == tidLst[i]) {\n                        used = true;\n                        break;\n                    }\n                }\n                if (!used) {\n                    tidLst.Add(tid);\n                    break;\n                }\n                else {\n                    tid += 1;\n                }\n            }\n        }\n\n        return tid;\n    }\n    private void RecycleTid() {\n        for (int i = 0; i < recTidLst.Count; i++) {\n            int tid = recTidLst[i];\n\n            for (int j = 0; j < tidLst.Count; j++) {\n                if (tidLst[j] == tid) {\n                    tidLst.RemoveAt(j);\n                    break;\n                }\n            }\n        }\n        recTidLst.Clear();\n    }\n    private void LogInfo(string info) {\n        if (taskLog != null) {\n            taskLog(info);\n        }\n    }\n    private double GetUTCMilliseconds() {\n        TimeSpan ts = DateTime.UtcNow - startDateTime;\n        return ts.TotalMilliseconds;\n    }\n    private string GetTimeStr(int time) {\n        if (time < 10) {\n            return \"0\" + time;\n        }\n        else {\n            return time.ToString();\n        }\n    }\n    #endregion\n\n    class PETimeTask {\n        public int tid;\n        public Action<int> callback;\n        public double destTime;\/\/\u5355\u4f4d\uff1a\u6beb\u79d2\n        public double delay;\n        public int count;\n\n        public PETimeTask(int tid, Action<int> callback, double destTime, double delay, int count) {\n            this.tid = tid;\n            this.callback = callback;\n            this.destTime = destTime;\n            this.delay = delay;\n            this.count = count;\n        }\n    }\n\n    class PEFrameTask {\n        public int tid;\n        public Action<int> callback;\n        public int destFrame;\n        public int delay;\n        public int count;\n\n        public PEFrameTask(int tid, Action<int> callback, int destFrame, int delay, int count) {\n            this.tid = tid;\n            this.callback = callback;\n            this.destFrame = destFrame;\n            this.delay = delay;\n            this.count = count;\n        }\n    }\n}\n\npublic enum PETimeUnit {\n    Millisecond,\n    Second,\n    Minute,\n    Hour,\n    Day\n}<\/pre>\n<h3>\n    \u4f7f\u7528\u793a\u4f8b\u4ee3\u7801<br \/>\n<\/h3>\n<p><strong>PETimer\u63a7\u5236\u53f0\u5de5\u7a0b\u6848\u4f8b\u4ee3\u7801\uff1a<\/strong>\n<\/p>\n<pre class=\"prettyprint lang-cs\">using System;\nusing System.Threading;\nusing System.Collections.Generic;\n\nnamespace ConsoleProjects {\n    class Program {\n        private static readonly string obj = \"lock\";\n\n        static void Main(string[] args) {\n            Console.WriteLine(\"Test Start!\");\n            \/\/Test1();\n            Test2();\n        }\n\n        \/\/\u7b2c\u4e00\u79cd\u7528\u6cd5\uff1a\u8fd0\u884c\u7ebf\u7a0b\u68c0\u6d4b\u5e76\u5904\u7406\u4efb\u52a1\n        static void Test1() {\n            \/\/\u8fd0\u884c\u7ebf\u7a0b\u9a71\u52a8\u8ba1\u65f6\n            PETimer pt = new PETimer();\n            pt.SetLog((string info) => {\n                Console.WriteLine(\"LogInfo:\" + info);\n            });\n\n            pt.AddTimeTask((int tid) => {\n                Console.WriteLine(\"Process\u7ebf\u7a0bID:{0}\", Thread.CurrentThread.ManagedThreadId.ToString());\n            }, 10, PETimeUnit.Millisecond, 0);\n\n            while (true) {\n                pt.Update();\n            }\n        }\n\n        \/\/\u7b2c\u4e8c\u79cd\u7528\u6cd5\uff1a\u72ec\u7acb\u7ebf\u7a0b\u68c0\u6d4b\u5e76\u5904\u7406\u4efb\u52a1\n        static void Test2() {\n            Queue<TaskPack> tpQue = new Queue<TaskPack>();\n            \/\/\u72ec\u7acb\u7ebf\u7a0b\u9a71\u52a8\u8ba1\u65f6\n            PETimer pt = new PETimer(5);\n            pt.SetLog((string info) => {\n                Console.WriteLine(\"LogInfo:\" + info);\n            });\n\n            int id = pt.AddTimeTask((int tid) => {\n                Console.WriteLine(\"Process\u7ebf\u7a0bID:{0}\", Thread.CurrentThread.ManagedThreadId.ToString());\n            }, 3000, PETimeUnit.Millisecond, 0);\n\n            \/\/\u8bbe\u7f6e\u56de\u8c03\u5904\u7406\u5668\n            \/*\n            pt.SetHandle((Action<int> cb, int tid) => {\n                if (cb != null) {\n                    lock (obj) {\n                        tpQue.Enqueue(new TaskPack(tid, cb));\n                    }\n                }\n            });\n            *\/\n            while (true) {\n                string ipt = Console.ReadLine();\n                if (ipt == \"a\") {\n                    pt.DeleteTimeTask(id);\n                }\n\n                if (tpQue.Count > 0) {\n                    TaskPack tp = null;\n                    lock (obj) {\n                        tp = tpQue.Dequeue();\n                    }\n                    tp.cb(tp.tid);\n                }\n            }\n        }\n    }\n\n    \/\/\u4efb\u52a1\u6570\u636e\u5305\n    class TaskPack {\n        public int tid;\n        public Action<int> cb;\n        public TaskPack(int tid, Action<int> cb) {\n            this.tid = tid;\n            this.cb = cb;\n        }\n    }\n}<\/pre>\n<p><strong>PETimer\u96c6\u6210\u5230Unity\u6848\u4f8b\u4ee3\u7801\uff1a<\/strong> <\/p>\n<\/p>\n<pre class=\"prettyprint lang-cs\">using UnityEngine;\n\npublic class GameStart : MonoBehaviour {\n    PETimer pt = new PETimer();\n\n    int tempID = -1;\n    private void Start() {\n        \/\/\u65f6\u95f4\u5b9a\u65f6\n        pt.AddTimeTask(TimerTask, 500, PETimeUnit.Millisecond, 3);\n        \/\/\u5e27\u6570\u5b9a\u65f6\n        pt.AddFrameTask(FrameTask, 100, 3);\n\n        \/\/\u5b9a\u65f6\u66ff\u6362\/\u5220\u9664\n        tempID = pt.AddTimeTask((int tid) => {\n            Debug.Log(\"\u5b9a\u65f6\u7b49\u5f85\u66ff\u6362......\");\n        }, 1, PETimeUnit.Second, 0);\n    }\n\n    private void Update() {\n        pt.Update();\n\n        \/\/\u5b9a\u65f6\u66ff\u6362\n        if (Input.GetKeyDown(KeyCode.R)) {\n\n            bool succ = pt.ReplaceTimeTask(tempID, (int tid) => {\n                Debug.Log(\"\u5b9a\u65f6\u7b49\u5f85\u5220\u9664......\");\n            }, 2, PETimeUnit.Second, 0);\n\n            if (succ) {\n                Debug.Log(\"\u66ff\u6362\u6210\u529f\");\n            }\n        }\n\n        \/\/\u5b9a\u65f6\u5220\u9664\n        if (Input.GetKeyDown(KeyCode.D)) {\n            pt.DeleteTimeTask(tempID);\n        }\n    }\n\n    void TimerTask(int tid) {\n        Debug.Log(\"TimeTask:\" + System.DateTime.UtcNow);\n    }\n\n    void FrameTask(int tid) {\n        Debug.Log(\"FrameTask:\" + System.DateTime.UtcNow);\n    }\n}<\/pre>\n<\/p>\n<div class=\"cke_widget_wrapper cke_widget_block cke_widget_codeSnippet cke_widget_wrapper_has cke_widget_selected\">\n<pre class=\"has cke_widget_element\"><\/pre>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>\u672c\u6587\u662f\u5b66\u4e60Siki\u5b66\u9662Plane\u8001\u5e08\u7684\u300a\u5b9a\u65f6\u56de\u8c03\u7cfb\u7edf\u6280\u672f\u4e13\u9898\u300b\u89c6\u9891\u8bfe\u7a0b\u7684\u5b66\u4e60\u7b14\u8bb0\u548c\u603b\u7ed3 \u5b9e\u73b0\u529f\u80fd \u652f\u6301\u65f6\u95f4\u5b9a\u65f6\uff0c\u5e27\u5b9a\u65f6 \u652f\u6301\u4efb\u52a1\u53ef\u5faa\u73af\uff0c\u53ef\u53d6\u6d88\uff0c\u53ef\u66ff\u6362 \u4f7f\u7528\u7b80\u5355\uff0c\u8c03\u7528\u65b9\u4fbf \u601d\u8def\uff1a \u5982\u4f55\u6269\u5c55\u5b9a\u65f6\u4efb\u52a1\uff1a\u5c06\u65f6\u95f4\u8ba1\u65f6\u8f6c\u4e3a\u5e27\u6570\u8ba1\u65f6 \u5982\u4f55\u6269\u5c55\u53d6\u6d88\/\u66ff\u6362\u5b9a\u65f6\u4efb\u52a1\uff1a\u751f\u6210\u552f\u4e00id,\u901a\u8fc7id\u7d22\u5f15\u64cd\u4f5c\u4efb\u52a1 \u5982\u4f55\u6269\u5c55\u5faa\u73af\u5b9a\u65f6\u4efb\u52a1\uff1a\u901a\u8fc7\u4efb\u52a1\u8ba1\u6570\u8fd0\u7b97 \u5982\u4f55\u6269\u5c55\u65f6\u95f4\u5355\u2026\u2026<\/p>","protected":false},"author":1,"featured_media":29,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[12],"tags":[9],"class_list":["post-27","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-unity","tag-unity"],"_links":{"self":[{"href":"https:\/\/www.blinkedu.cn\/index.php\/wp-json\/wp\/v2\/posts\/27"}],"collection":[{"href":"https:\/\/www.blinkedu.cn\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.blinkedu.cn\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.blinkedu.cn\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.blinkedu.cn\/index.php\/wp-json\/wp\/v2\/comments?post=27"}],"version-history":[{"count":1,"href":"https:\/\/www.blinkedu.cn\/index.php\/wp-json\/wp\/v2\/posts\/27\/revisions"}],"predecessor-version":[{"id":92,"href":"https:\/\/www.blinkedu.cn\/index.php\/wp-json\/wp\/v2\/posts\/27\/revisions\/92"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.blinkedu.cn\/index.php\/wp-json\/wp\/v2\/media\/29"}],"wp:attachment":[{"href":"https:\/\/www.blinkedu.cn\/index.php\/wp-json\/wp\/v2\/media?parent=27"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.blinkedu.cn\/index.php\/wp-json\/wp\/v2\/categories?post=27"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.blinkedu.cn\/index.php\/wp-json\/wp\/v2\/tags?post=27"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}