in src/Threads/TimerEx.cs [892:1015]
public void Run()
{
while (true)
{
TimerTask task;
lock (this.syncRoot)
{
// need to check cancelled inside the synchronized block
if (cancelled)
{
return;
}
if (tasks.IsEmpty())
{
if (finished)
{
return;
}
// no tasks scheduled -- sleep until any task appear
try
{
Monitor.Wait(this.syncRoot);
}
catch (ThreadInterruptedException)
{
}
continue;
}
DateTime currentTime = DateTime.Now;
task = tasks.Minimum();
TimeSpan timeToSleep;
lock (task.syncRoot)
{
if (task.cancelled)
{
tasks.Delete(0);
continue;
}
// check the time to sleep for the first task scheduled
timeToSleep = task.when - currentTime;
}
if (timeToSleep.CompareTo(TimeSpan.Zero) > 0)
{
// sleep!
try
{
Monitor.Wait(this.syncRoot, timeToSleep);
}
catch (ThreadInterruptedException)
{
}
continue;
}
// no sleep is necessary before launching the task
lock (task.syncRoot)
{
int pos = 0;
if (tasks.Minimum().when != task.when)
{
pos = tasks.GetTask(task);
}
if (task.cancelled)
{
tasks.Delete(tasks.GetTask(task));
continue;
}
// set time to schedule
task.ScheduledTime = task.when;
// remove task from queue
tasks.Delete(pos);
// set when the next task should be launched
if (task.period.CompareTo(TimeSpan.Zero) >= 0)
{
// this is a repeating task,
if (task.fixedRate)
{
// task is scheduled at fixed rate
task.when = task.when + task.period;
}
else
{
// task is scheduled at fixed delay
task.when = DateTime.Now + task.period;
}
// insert this task into queue
InsertTask(task);
}
else
{
task.when = DateTime.MinValue;
}
}
}
bool taskCompletedNormally = false;
try
{
task.Run();
taskCompletedNormally = true;
}
finally
{
if (!taskCompletedNormally)
{
lock (this)
{
cancelled = true;
}
}
}
}
}