using System; using System.Linq; using System.Threading; using System.Threading.Tasks; 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 SemaphoreSlim Lock = new(1, 1); private static readonly SemaphoreSlim PoolLock = new(16, 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.WaitAsync(); Lock.Release(); } return; } await Lock.WaitAsync(); try { var tasks = Global.Settings.Server.Select(async s => { await PoolLock.WaitAsync(); try { await s.PingAsync(); } finally { PoolLock.Release(); } }); await Task.WhenAll(tasks); } catch (Exception) { // ignored } finally { Lock.Release(); } } 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(); } } } }