using System; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; namespace ChaosBot.Services { public static class Timer { private static Dictionary _timers = new Dictionary(); private static int _nextTimerIndex = 0; private static int NextTimerIndex { get { _nextTimerIndex++; return _nextTimerIndex; } } public static int RunAt(Action toRun, DateTime deadlineTime) { DateTime current = DateTime.Now; TimeSpan timeToGo = deadlineTime - current; if (timeToGo < TimeSpan.Zero) { return -1; //time already passed } int timerIndex = NextTimerIndex; _timers.Add(timerIndex, new System.Threading.Timer(x => { toRun(); _timers.Remove(timerIndex); }, null, timeToGo, Timeout.InfiniteTimeSpan)); return timerIndex; } public static int RunIn(Action toRun, TimeSpan dueTime) { DateTime current = DateTime.Now; if (dueTime < TimeSpan.Zero) { return -1; //time already passed } int timerIndex = NextTimerIndex; _timers.Add(timerIndex, new System.Threading.Timer(x => { toRun(); _timers.Remove(timerIndex); }, null, dueTime, Timeout.InfiniteTimeSpan)); return timerIndex; } public static int RunTimer(Action toRun, TimeSpan interval) { return RunTimer(toRun, interval, TimeSpan.Zero); } public static int RunTimer(Action toRun, TimeSpan interval, TimeSpan offset) { DateTime current = DateTime.Now; if (offset < TimeSpan.Zero) { return -1; //time already passed } int timerIndex = NextTimerIndex; void Callback() { toRun(); if (_timers.ContainsKey(timerIndex)) _timers.Remove(timerIndex); _timers.Add(timerIndex, new System.Threading.Timer(x => { Callback(); }, null, interval, Timeout.InfiniteTimeSpan)); } if (offset > TimeSpan.Zero) { _timers.Add(timerIndex, new System.Threading.Timer(x => { Callback(); }, null, offset, Timeout.InfiniteTimeSpan)); } else { Callback(); } return timerIndex; } public static void CancelTimer(int id) { if (id < 0) return; if (!_timers.ContainsKey(id)) return; _timers.GetValueOrDefault(id)?.Dispose(); if (_timers.ContainsKey(id)) _timers.Remove(id); } public static void Join(int id) { if (id < 0) return; while (_timers.ContainsKey(id)) { Thread.Sleep(500); } } } }