using System;
using System.Collections.Generic;
using System.Threading;
using System.Timers;
namespace NetSnippetsQuickTest
{
public interface ICommand
{
bool Execute();
Guid Id { get; }
}
class Scheduler
{
List<ICommand> _commands;
public readonly double SchedulingIntervalInMilliSeconds;
public readonly int ExecutionRecurrences;
int currentCommandIndex = 0;
int currentRecurrence = 0;
System.Timers.Timer _schedulingTimer;
AutoResetEvent stopFlag;
//CTOR with miliseconds use SchedulingIntervalInSeconds with x.0 or (double)
public Scheduler(List<ICommand> Commands, double SchedulingIntervalInSeconds, int ExecutionRecurrences)
{
_commands = Commands;
this.ExecutionRecurrences = ExecutionRecurrences;
this.SchedulingIntervalInMilliSeconds = SchedulingIntervalInSeconds;
}
//CTOR with Minutes
public Scheduler(List<ICommand> Commands, int SchedulingIntervalInMinutes, int ExecutionRecurrences)
: this(Commands, ((double)SchedulingIntervalInMinutes * 60 * 1000), ExecutionRecurrences)
{
}
public System.Collections.ObjectModel.ReadOnlyCollection<ICommand> Commands
{
get { return _commands.AsReadOnly(); }
}
public void Run()
{
//reset counter
currentCommandIndex = 0;
currentRecurrence = 0;
stopFlag = new AutoResetEvent(false);
_schedulingTimer = new System.Timers.Timer();
//intervall is milliseconds
_schedulingTimer.Interval = SchedulingIntervalInMilliSeconds;
_schedulingTimer.Elapsed += new ElapsedEventHandler(_schedulingTimer_Elapsed);
_schedulingTimer.Enabled = true;
//pause current thread here until scheduling is done
stopFlag.WaitOne();
//got signal from stopFlag so execution is finished
}
public bool IsFinished
{
get { return currentRecurrence == ExecutionRecurrences && currentCommandIndex == _commands.Count; }
}
void _schedulingTimer_Elapsed(object sender, ElapsedEventArgs e)
{
//multiple timer calls spawn multiple threads so we have to sync this
//so only one thread should execute this code
lock (sender)
{
//maybe antoher thread has finished execution and we were blocked so we our job is done
if (!IsFinished)
{
//avoid out of range
ICommand cmd = (currentCommandIndex >= _commands.Count ? null : _commands[currentCommandIndex]);
if (cmd != null)
{
cmd.Execute();
currentCommandIndex++;
}
//we have reached the last command in queue so reset command index
if (currentCommandIndex == _commands.Count)
{
currentRecurrence++;
//we´re finished all necessary runs
if (IsFinished)
{
_schedulingTimer.Enabled = false;
stopFlag.Set();
}
else
{
currentCommandIndex = 0;
}
}
}
}
}
}
}