public class CachedThrottle<T> { private readonly Func<Task<T>> fn; private T data = default(T); private DateTime? Last = null; private readonly TimeSpan ThrottleTime; private readonly object locker = new(); public CachedThrottle(Func<Task<T>> initialFn, TimeSpan throttleTime) { fn = initialFn; ThrottleTime = throttleTime; } public async Task<T> Load() { Last = DateTime.Now; try { data = await fn(); } catch (System.Exception) { Last = null; throw; } return data; } public T Get() { TriggerUpdate(); return data; } public async Task<T> GetAsync() { if (IsElapsed()) { Last = DateTime.Now; return await Load(); } return data; } public void TriggerUpdate() { lock (locker) { if (IsElapsed()) { Last = DateTime.Now; Task.Run(Load); } } } public bool IsElapsed() => Last == null || (DateTime.Now - Last).Value > ThrottleTime; } // Example public class Program { public static CachedThrottle<string> Content = new(() => { Console.WriteLine("ReadingFile"); return File.ReadAllTextAsync(@"C:\temp\test.txt"); }, TimeSpan.FromSeconds(2)); public static async Task Main() { await Content.Load(); Console.WriteLine($"A: {Content.Get()}"); Console.WriteLine($"B: {Content.Get()}"); await Task.Delay(1000); Console.WriteLine($"C: {Content.Get()}"); await Task.Delay(2000); Console.WriteLine($"D: {Content.Get()}"); } }
829200cookie-checkC# Throttle Function