/// <summary> /// Callback from the TickManager. Runs the next tasks in the queue until /// </summary> private void RunNextTask() { BaseTask taskToRun = null; bool firstRun = true; while (true) { lock (tasks) { tickManagerRequest = null; //This better be called because tickManagerRequest is running, so assume it's something and clear it here. It needs to be done during a lock though. if (firstRun) { if (runningTask) //something has gone horribly wrong. TODO: Log an error. { return; } } else { if (!runningTask) //something has gone horribly wrong. TODO: Log an error. { return; } runningTask = false; } while (true) { if (tasks.Count == 0) { return; } taskToRun = tasks[0]; if (taskToRun.IsCanceled()) { tasks.RemoveAt(0); continue; } if (taskToRun.scheduledTime > DateTime.UtcNow.AddMilliseconds(TickManager.NowLimit)) { WaitToNextTask(taskToRun); return; } taskToRun = tasks.RemoveAt(0); break; } runningTask = true; } firstRun = false; taskToRun.Start(); } }
/// <summary> /// Should only be called while the caller is in lock(tasks). Queues /// </summary> private void WaitToNextTask(BaseTask nextTask = null) { if (nextTask == null) { if (tasks.Count == 0) { tickManagerRequest = null; return; } nextTask = tasks[0]; } tickManagerRequest = TickManager.Add(RunNextTask, nextTask.scheduledTime); }
private void AddTask(BaseTask task) { lock (tasks) { int index = tasks.BinarySearch(task); if (index < 0) { index = ~index; } tasks.Insert(index, task); if (!runningTask && index == 0) { if (tickManagerRequest != null) { bool wasCanceled; if (tickManagerRequest.Cancel(out wasCanceled)) { if (wasCanceled) { //need to submit a new task WaitToNextTask(task); } else { //another thread canceled it already? This seems invalid. TODO: Log an error probably } } //else don't need to do anything, another thread will get to it. Semi-race condition where the other thread //is probably waiting on this lock. } else { //need to submit a new task WaitToNextTask(task); } } } }