If you're looking to manage time events in your code, consider creating a static class called Timeman. This class will handle all your timed actions.
Create separate packages for each action that begins with a delay and name them TimemanEvent.
Below is an example of how to use this concept along with the corresponding source code:
// Register a timed event
var id = Timeman.SetTimeout(() => {
Console.log("Code executed successfully");
}, 3000);
// OR
var id = Timeman.SetTimeout(MyMethod, 3000);
// Cancel the event
Timeman.ClearTimeout(id);
public class Timeman {
private static readonly ConcurrentDictionary<int, TimemanEvent> InnerDic;
static Timeman() {
InnerDic = new ConcurrentDictionary<int, TimemanEvent>();
}
/// <summary> Generate Unique Dictionary Id </summary>
private static int GetUniqueId() {
// If dict is empty take zero
if (InnerDic.Keys.Count == 0) return 0;
// If there is only one, take next
if (InnerDic.Keys.Count == 1) return InnerDic.Keys.First() + 1;
// Get all id numbers
var allKeys = InnerDic.Keys.ToList();
// Check the missing numbers in order.
allKeys.Sort();
var firstNumber = allKeys.First();
var lastNumber = allKeys.Last();
var missingNumbers = Enumerable.Range(firstNumber, lastNumber).Except(allKeys);
// If missing numbers are found, take the first one
if (missingNumbers.Count() > 0) return missingNumbers.First();
// Take next
return lastNumber + 1;
}
/// <summary>
/// Executes the method after a specified time interval (ms).
/// <code>
/// var id = Timeman.SetTimeout(() => {
/// Console.log("Code executed successfully");
/// }, 3000);
/// OR
/// var id = Timeman.SetTimeout(MyMethod, 3000);
/// </code>
/// </summary>
public static int SetTimeout(Action action, int delayMs) {
var uniqueId = GetUniqueId();
var te = new TimemanEvent(uniqueId, action, delayMs);
InnerDic.TryAdd(uniqueId, te);
te.Start();
return uniqueId;
}
/// <summary>
/// Cancels the execution of a timeout before completion.
/// <code>
/// Timeman.ClearTimeout(id);
/// </code>
/// </summary>
public static void ClearTimeout(int id) {
if (InnerDic.TryRemove(id, out var tEvent))
tEvent?.Dispose();
}
}
internal class TimemanEvent {
private readonly Action action;
private readonly Timer timer;
private readonly int id;
public TimemanEvent(int id, Action action, int delayMs) {
this.id = id;
this.action = action;
this.timer = new Timer
{
Interval = delayMs
};
timer.Tick += OnTimerTick;
}
private void OnTimerTick(object sender, EventArgs e) {
action();
Timeman.ClearTimeout(id);
}
/// <summary> Stop timer and unregister events </summary>
internal void Dispose() {
timer.Tick -= OnTimerTick;
Stop();
}
internal void Start() => timer.Start();
internal void Stop() => timer.Stop();
}