using Microsoft.VisualStudio.Threading; using Netch.Models; using Timer = System.Timers.Timer; namespace Netch.Utils; public static class DelayTestHelper { private static readonly Timer Timer; private static readonly AsyncSemaphore Lock = new(1); private static readonly AsyncSemaphore PoolLock = new(16); public static readonly NumberRange Range = new(0, int.MaxValue / 1000); private static bool _enabled = true; static DelayTestHelper() { Timer = new Timer { Interval = 10000, AutoReset = true }; Timer.Elapsed += (_, _) => PerformTestAsync().Forget(); } public static bool Enabled { get => _enabled; set { _enabled = value; UpdateTick(); } } /// if does not get lock, block until last release public static async Task PerformTestAsync(bool waitFinish = false) { if (Lock.CurrentCount == 0) { if (waitFinish) (await Lock.EnterAsync()).Dispose(); return; } using var _ = await Lock.EnterAsync(); try { var tasks = Global.Settings.Server.Select(async s => { using (await PoolLock.EnterAsync()) { await s.PingAsync(); } }); await Task.WhenAll(tasks); } catch (Exception) { // ignored } } public static void UpdateTick(bool performTestAtOnce = false) { UpdateTick(Global.Settings.DetectionTick, performTestAtOnce); } /// interval(seconds), 0 disable, MaxValue int.MaxValue/1000 /// private static void UpdateTick(int interval, bool performTestAtOnce = false) { Timer.Stop(); var enable = Enabled && interval > 0 && Range.InRange(interval); if (enable) { Timer.Interval = interval * 1000; Timer.Start(); if (performTestAtOnce) PerformTestAsync().Forget(); } } }