using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; namespace ETModel { public struct Timer { public long Id { get; set; } public long Time { get; set; } public TaskCompletionSource tcs; } [ObjectSystem] public class TimerComponentUpdateSystem : UpdateSystem { public override void Update(TimerComponent self) { self.Update(); } } public class TimerComponent : Component { private readonly Dictionary timers = new Dictionary(); /// /// key: time, value: timer id /// private readonly MultiMap timeId = new MultiMap(); private readonly List timeOutTime = new List(); // 记录最小时间,不用每次都去MultiMap取第一个值 private long minTime; public void Update() { if (this.timeId.Count == 0) { return; } long timeNow = TimeHelper.Now(); if (timeNow < this.minTime) { return; } this.timeOutTime.Clear(); foreach (KeyValuePair> kv in this.timeId.GetDictionary()) { long k = kv.Key; if (k > timeNow) { minTime = k; break; } this.timeOutTime.Add(k); } foreach (long k in this.timeOutTime) { foreach (long v in this.timeId[k]) { Timer timer; if (!this.timers.TryGetValue(v, out timer)) { continue; } this.timers.Remove(v); timer.tcs.SetResult(true); } this.timeId.Remove(k); } } private void Remove(long id) { Timer timer; if (!this.timers.TryGetValue(id, out timer)) { return; } this.timers.Remove(id); } public Task WaitTillAsync(long tillTime, CancellationToken cancellationToken) { TaskCompletionSource tcs = new TaskCompletionSource(); Timer timer = new Timer { Id = IdGenerater.GenerateId(), Time = tillTime, tcs = tcs }; this.timers[timer.Id] = timer; this.timeId.Add(timer.Time, timer.Id); if (timer.Time < this.minTime) { this.minTime = timer.Time; } cancellationToken.Register(() => { this.Remove(timer.Id); }); return tcs.Task; } public Task WaitTillAsync(long tillTime) { TaskCompletionSource tcs = new TaskCompletionSource(); Timer timer = new Timer { Id = IdGenerater.GenerateId(), Time = tillTime, tcs = tcs }; this.timers[timer.Id] = timer; this.timeId.Add(timer.Time, timer.Id); if (timer.Time < this.minTime) { this.minTime = timer.Time; } return tcs.Task; } public Task WaitAsync(long time, CancellationToken cancellationToken) { TaskCompletionSource tcs = new TaskCompletionSource(); Timer timer = new Timer { Id = IdGenerater.GenerateId(), Time = TimeHelper.Now() + time, tcs = tcs }; this.timers[timer.Id] = timer; this.timeId.Add(timer.Time, timer.Id); if (timer.Time < this.minTime) { this.minTime = timer.Time; } cancellationToken.Register(() => { this.Remove(timer.Id); }); return tcs.Task; } public Task WaitAsync(long time) { TaskCompletionSource tcs = new TaskCompletionSource(); Timer timer = new Timer { Id = IdGenerater.GenerateId(), Time = TimeHelper.Now() + time, tcs = tcs }; this.timers[timer.Id] = timer; this.timeId.Add(timer.Time, timer.Id); if (timer.Time < this.minTime) { this.minTime = timer.Time; } return tcs.Task; } } }