using System.Collections.Generic;
using System.Threading.Tasks;
public sealed class SchedulerTask
public TimeSpan Interval { get; }
this.Interval = TimeSpan.FromSeconds(Random.Shared.Next(1, 30));
Console.WriteLine(this.Interval);
var startTime = DateTime.UtcNow;
var endTime = startTime + TimeSpan.FromMilliseconds(Random.Shared.Next(500, 1500));
while (DateTime.UtcNow < endTime);
private Executor Executor;
private Interval Interval;
private List<SchedulerTask> Tasks;
public Scheduler(List<SchedulerTask> tasks)
this.Executor = new Executor();
this.Interval = new Interval(this.Executor);
CancellationToken token = new CancellationToken();
foreach (SchedulerTask task in this.Tasks)
this.Interval.Add(task.Interval, task.Calculate);
return this.Executor.Run(token);
private Executor Executor;
private List<System.Timers.Timer> Timers;
public Interval(Executor executor)
this.Executor = executor;
this.Timers = new List<System.Timers.Timer>();
public void Add(TimeSpan timeSpan, Action action)
System.Timers.Timer timer = new System.Timers.Timer(timeSpan.TotalMilliseconds);
timer.Elapsed += (Object source, ElapsedEventArgs e) =>
this.Executor.Add(action);
foreach (System.Timers.Timer timer in this.Timers)
private static int BatchSize = 8;
private Queue<Action> Queue;
this.Queue = new Queue<Action>();
public void Add(Action fn)
public async Task Run(CancellationToken cancellationToken)
await this.RunBatch(cancellationToken);
private async Task RunBatch(CancellationToken cancellationToken)
if (this.Queue.Count == 0)
await Task.Delay(50, cancellationToken);
List<Task> tasks = new List<Task>();
for (int i = 0; i < Executor.BatchSize && this.Queue.Count > 0; i++)
Action action = this.Queue.Dequeue();
tasks.Add(Task.Run(action));
await Task.WhenAll(tasks.ToArray());
public async static Task Main()
List<SchedulerTask> tasks = new List<SchedulerTask>();
tasks.Add(new SchedulerTask());
tasks.Add(new SchedulerTask());
tasks.Add(new SchedulerTask());
Scheduler scheduler = new Scheduler(tasks);