/// <summary> /// constructor /// </summary> /// <param name="numSlots">总槽数,越大则槽冲突越小</param> /// <param name="slotInterval">槽间隔,越小精度越高,单位毫秒</param> /// <param name="dateTimeProvider">获取当前DateTime的函数</param> private TimerScheduler(int numSlots, int slotInterval, Func <DateTime> dateTimeProvider) { this.slots = new List <TimerNode>(numSlots); for (int i = 0; i < numSlots; ++i) { var node = new TimerNode(); node.LinkSelf(); slots.Add(node); } this.tempSlot = new TimerNode(); this.tempSlot.LinkSelf(); this.slotInterval = new TimeSpan(0, 0, 0, 0, slotInterval); this.DateTimeProvider = dateTimeProvider; this.startTime = dateTimeProvider(); this.lastFiredSlot = -1; this.lastFiredTime = this.startTime - this.slotInterval; var dispatcher = SimpleDispatcher.CurrentDispatcher; TimerCallback callback = (state) => { dispatcher.Invoke(this.Update); }; this.updateTimer = new System.Threading.Timer(callback, null, new TimeSpan(0, 0, 0, 0, slotInterval / 2), new TimeSpan(0, 0, 0, 0, slotInterval)); }
private void Update() { var now = DateTimeProvider(); while (lastFiredTime + slotInterval < now) { lastFiredTime += slotInterval; lastFiredSlot = (lastFiredSlot + 1) % slots.Count; var slot = slots[lastFiredSlot]; while (slot.Next != slot) { var timer = slot.Next as Timer; timer.Unlink(); if (timer.Circles > 0) { --timer.Circles; timer.LinkAfter(tempSlot); continue; } timer.OnTick(); } if (tempSlot.Next != tempSlot) { slots[lastFiredSlot] = tempSlot; tempSlot = slot; } } }
internal void Unlink() { if (Prev != null) Prev.Next = Next; if (Next != null) Next.Prev = Prev; Prev = null; Next = null; }
internal void LinkBefore(TimerNode node) { Unlink(); if (node.Prev != null) { node.Prev.Next = this; this.Prev = node.Prev; } node.Prev = this; this.Next = node; }
internal void LinkAfter(TimerNode node) { Unlink(); if (node.Next != null) { node.Next.Prev = this; this.Next = node.Next; } node.Next = this; this.Prev = node; }
internal void Unlink() { if (Prev != null) { Prev.Next = Next; } if (Next != null) { Next.Prev = Prev; } Prev = null; Next = null; }
internal void LinkSelf() { Unlink(); Prev = this; Next = this; }