Kaynağa Gözat

修复两个极其隐蔽的bug,计时器跟协程锁,都是对象池导致的

tanghai 3 yıl önce
ebeveyn
işleme
1e751d17b6

+ 3 - 7
Unity/Assets/Scripts/Core/Module/CoroutineLock/CoroutineLockQueue.cs

@@ -3,7 +3,7 @@ using System.Collections.Generic;
 
 namespace ET
 {
-    public class CoroutineLockQueue: IDisposable
+    public class CoroutineLockQueue
     {
         private int type;
         private long key;
@@ -65,13 +65,9 @@ namespace ET
             }
         }
 
-        public void Dispose()
+        public void Recycle()
         {
-            while (this.queue.Count > 0)
-            {
-                WaitCoroutineLock waitCoroutineLock = this.queue.Dequeue();
-                waitCoroutineLock.Dispose();
-            }
+            this.queue.Clear();
             this.key = 0;
             this.type = 0;
             this.currentCoroutineLock = null;

+ 1 - 1
Unity/Assets/Scripts/Core/Module/CoroutineLock/CoroutineLockQueueType.cs

@@ -30,7 +30,7 @@ namespace ET
         {
             if (this.coroutineLockQueues.Remove(key, out CoroutineLockQueue queue))
             {
-                queue.Dispose();
+                queue.Recycle();
             }
         }
 

+ 3 - 8
Unity/Assets/Scripts/Core/Module/CoroutineLock/WaitCoroutineLock.cs

@@ -1,4 +1,5 @@
 using System;
+using System.Threading;
 
 namespace ET
 {
@@ -15,11 +16,11 @@ namespace ET
         }
     }
     
-    public class WaitCoroutineLock: IDisposable
+    public class WaitCoroutineLock
     {
         public static WaitCoroutineLock Create()
         {
-            WaitCoroutineLock waitCoroutineLock = ObjectPool.Instance.Fetch<WaitCoroutineLock>();
+            WaitCoroutineLock waitCoroutineLock = new WaitCoroutineLock();
             waitCoroutineLock.tcs = ETTask<CoroutineLock>.Create(true);
             return waitCoroutineLock;
         }
@@ -57,11 +58,5 @@ namespace ET
         {
             return await this.tcs;
         }
-
-        public void Dispose()
-        {
-            this.tcs = null;
-            ObjectPool.Instance.Recycle(this);
-        }
     }
 }

+ 45 - 39
Unity/Assets/Scripts/Core/Module/Timer/TimerComponent.cs

@@ -1,5 +1,4 @@
-using System;
-using System.Collections.Generic;
+using System.Collections.Generic;
 
 namespace ET
 {
@@ -11,12 +10,14 @@ namespace ET
         RepeatedTimer,
     }
 
-    public class TimerAction: IDisposable
+    public class TimerAction
     {
-        public static TimerAction Create(TimerClass timerClass, long time, int type, object obj)
+        public static TimerAction Create(long id, TimerClass timerClass, long startTime, long time, int type, object obj)
         {
             TimerAction timerAction = ObjectPool.Instance.Fetch<TimerAction>();
+            timerAction.Id = id;
             timerAction.TimerClass = timerClass;
+            timerAction.StartTime = startTime;
             timerAction.Object = obj;
             timerAction.Time = time;
             timerAction.Type = type;
@@ -29,13 +30,17 @@ namespace ET
 
         public object Object;
 
+        public long StartTime;
+
         public long Time;
 
         public int Type;
         
-        public void Dispose()
+        public void Recycle()
         {
+            this.Id = 0;
             this.Object = null;
+            this.StartTime = 0;
             this.Time = 0;
             this.TimerClass = TimerClass.None;
             this.Type = 0;
@@ -60,20 +65,23 @@ namespace ET
 
         private readonly Queue<long> timeOutTimerIds = new Queue<long>();
 
-        public readonly Queue<long> everyFrameTimer = new Queue<long>();
-
         private readonly Dictionary<long, TimerAction> timerActions = new Dictionary<long, TimerAction>();
 
         private long idGenerator;
 
         // 记录最小时间,不用每次都去MultiMap取第一个值
-        private long minTime;
+        private long minTime = long.MaxValue;
 
         private long GetId()
         {
             return ++this.idGenerator;
         }
 
+        private static long GetNow()
+        {
+            return TimeHelper.ClientFrameTime();
+        }
+
         public void Update()
         {
             if (this.TimeId.Count == 0)
@@ -81,7 +89,7 @@ namespace ET
                 return;
             }
 
-            long timeNow = TimeHelper.ClientNow();
+            long timeNow = GetNow();
 
             if (timeNow < this.minTime)
             {
@@ -109,7 +117,6 @@ namespace ET
                     long timerId = list[i];
                     this.timeOutTimerIds.Enqueue(timerId);
                 }
-
                 this.TimeId.Remove(time);
             }
 
@@ -117,12 +124,11 @@ namespace ET
             {
                 long timerId = this.timeOutTimerIds.Dequeue();
 
-                this.timerActions.TryGetValue(timerId, out TimerAction timerAction);
-                if (timerAction == null)
+                if (!this.timerActions.Remove(timerId, out TimerAction timerAction))
                 {
                     continue;
                 }
-
+                
                 this.Run(timerAction);
             }
         }
@@ -133,31 +139,31 @@ namespace ET
             {
                 case TimerClass.OnceTimer:
                 {
-                    int type = timerAction.Type;
-                    EventSystem.Instance.Callback(new TimerCallback() { Id = type, Args = timerAction.Object });
+                    EventSystem.Instance.Callback(new TimerCallback() { Id = timerAction.Type, Args = timerAction.Object });
+                    timerAction.Recycle();
                     break;
                 }
                 case TimerClass.OnceWaitTimer:
                 {
                     ETTask<bool> tcs = timerAction.Object as ETTask<bool>;
-                    this.Remove(timerAction.Id);
                     tcs.SetResult(true);
+                    timerAction.Recycle();
                     break;
                 }
                 case TimerClass.RepeatedTimer:
-                {
-                    int type = timerAction.Type;
-                    long tillTime = TimeHelper.ClientNow() + timerAction.Time;
-                    this.AddTimer(tillTime, timerAction);
-                    EventSystem.Instance.Callback(new TimerCallback() { Id = type, Args = timerAction.Object });
+                {                    
+                    long timeNow = GetNow();
+                    timerAction.StartTime = timeNow;
+                    this.AddTimer(timerAction);
+                    EventSystem.Instance.Callback(new TimerCallback() { Id = timerAction.Type, Args = timerAction.Object });
                     break;
                 }
             }
         }
 
-        private void AddTimer(long tillTime, TimerAction timer)
+        private void AddTimer(TimerAction timer)
         {
-            timer.Id = this.GetId();
+            long tillTime = timer.StartTime + timer.Time;
             this.TimeId.Add(tillTime, timer.Id);
             this.timerActions.Add(timer.Id, timer);
             if (tillTime < this.minTime)
@@ -180,27 +186,25 @@ namespace ET
                 return false;
             }
 
-            this.timerActions.TryGetValue(id, out TimerAction timerAction);
-            if (timerAction == null)
+            if (!this.timerActions.Remove(id, out TimerAction timerAction))
             {
                 return false;
             }
-
-            timerAction.Dispose();
+            timerAction.Recycle();
             return true;
         }
 
         public async ETTask<bool> WaitTillAsync(long tillTime, ETCancellationToken cancellationToken = null)
         {
-            long timeNow = TimeHelper.ClientNow();
+            long timeNow = GetNow();
             if (timeNow >= tillTime)
             {
                 return true;
             }
 
             ETTask<bool> tcs = ETTask<bool>.Create(true);
-            TimerAction timer = TimerAction.Create(TimerClass.OnceWaitTimer, tillTime - timeNow, 0, tcs);
-            this.AddTimer(tillTime, timer);
+            TimerAction timer = TimerAction.Create(this.GetId(), TimerClass.OnceWaitTimer, timeNow, tillTime - timeNow, 0, tcs);
+            this.AddTimer(timer);
             long timerId = timer.Id;
 
             void CancelAction()
@@ -238,11 +242,11 @@ namespace ET
                 return true;
             }
 
-            long tillTime = TimeHelper.ClientNow() + time;
+            long timeNow = GetNow();
 
             ETTask<bool> tcs = ETTask<bool>.Create(true);
-            TimerAction timer = TimerAction.Create(TimerClass.OnceWaitTimer, time, 0, tcs);
-            this.AddTimer(tillTime, timer);
+            TimerAction timer = TimerAction.Create(this.GetId(), TimerClass.OnceWaitTimer, timeNow, time, 0, tcs);
+            this.AddTimer(timer);
             long timerId = timer.Id;
 
             void CancelAction()
@@ -272,13 +276,14 @@ namespace ET
         // wait时间长不需要逻辑连贯的建议用NewOnceTimer
         public long NewOnceTimer(long tillTime, int type, object args)
         {
-            if (tillTime < TimeHelper.ClientNow())
+            long timeNow = GetNow();
+            if (tillTime < timeNow)
             {
                 Log.Error($"new once time too small: {tillTime}");
             }
 
-            TimerAction timer = TimerAction.Create(TimerClass.OnceTimer, tillTime, type, args);
-            this.AddTimer(tillTime, timer);
+            TimerAction timer = TimerAction.Create(this.GetId(), TimerClass.OnceTimer, timeNow, tillTime - timeNow, type, args);
+            this.AddTimer(timer);
             return timer.Id;
         }
 
@@ -302,11 +307,12 @@ namespace ET
                 throw new Exception($"repeated timer < 100, timerType: time: {time}");
             }
 #endif
-            long tillTime = TimeHelper.ClientNow() + time;
-            TimerAction timer = TimerAction.Create(TimerClass.RepeatedTimer, time, type, args);
+            
+            long timeNow = GetNow();
+            TimerAction timer = TimerAction.Create(this.GetId(), TimerClass.RepeatedTimer, timeNow, time, type, args);
 
             // 每帧执行的不用加到timerId中,防止遍历
-            this.AddTimer(tillTime, timer);
+            this.AddTimer(timer);
             return timer.Id;
         }
 

+ 1 - 1
Unity/Assets/Scripts/Core/TimerCoreCallbackId.cs

@@ -2,6 +2,6 @@
 {
     public static class TimerCoreCallbackId
     {
-        public const int CoroutineTimeout = 1;
+        public const int CoroutineTimeout = 10000;
     }
 }