using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; namespace Model { 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 timeOutId = new List(); public void Update() { long timeNow = TimeHelper.Now(); while (true) { if (this.timeId.Count <= 0) { return; } var kv = this.timeId.First(); if (kv.Key > timeNow) { break; } timeOutId.Clear(); timeOutId.AddRange(kv.Value); this.timeId.Remove(kv.Key); foreach (long id in timeOutId) { Timer timer; if (!this.timers.TryGetValue(id, out timer)) { continue; } this.timers.Remove(id); timer.tcs.SetResult(true); } } } 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); 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); 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); 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); return tcs.Task; } } }