/// <summary> /// Runs all tasks until no more scheduled tasks are left. /// If a pending task schedules an additional task it will also be executed. /// </summary> public void RunTasksUntilIdle() { while (ScheduledTasks.Any()) { RunPendingTasks(); } }
private void TaskManagerWorkerLoop() { if (TaskManagerWorkerTask != null && TaskManagerWorkerTask.Status == TaskStatus.Running) { return; } TaskQueueStarted?.Invoke(this, new EventArgs()); var lastLog = DateTime.Now; TaskManagerWorkerTask = Task.Run(() => { Logger.LogInformation("Started QueueManagerTask loop at Task ID {0}", Task.CurrentId); while (ActiveTasks.Any() || ScheduledTasks.Any()) { if (!Running.Wait(500)) { continue; } Thread.Sleep(500); if ((DateTime.Now - lastLog).Seconds > WORKER_LOOP_LOGGER_INTERVAL_SECS) { lastLog = DateTime.Now; Logger.LogInformation("Active: {1} <{#!#}> Running: {2} <{#!#}> Scheduled: {3}", ActiveTasks.Count, ActiveTasks.Count(t => t.Key.Status == TaskStatus.Running), ScheduledTasks.Count); } lock (ActiveTasks) { foreach (var task in ActiveTasks.Where(t => t.Key.Status == TaskStatus.Created)) { Logger.LogDebug("Starting Task ID {0}", task.Key.Id); try { task.Key.Start(); task.Key.ContinueWith(t => { ActiveTasks.TryRemove(t, out var emptyVar); Logger.LogDebug("Task ID {0} has completed", t.Id); TaskCompleted?.Invoke(this, task.Key); }); TaskStarted?.Invoke(this, task.Key); } catch (Exception ex) { Logger.LogCritical(ex, "Error starting task {0}", task.Key.Id); } } } while (ActiveTasks.Count < MaximumConcurrentThreads && ScheduledTasks.Any()) { // Keep TaskManager full to maximum by dequeueing scheduled tasks // TODO: If these Try*s fail, weird things will happen; need to handle false cases if (ScheduledTasks.TryDequeue(out var task)) { Logger.LogDebug("Moving status of Task {0} from {1} to {2} ", task.Id, "scheduled", "active"); ActiveTasks.TryAdd(task, false); } } } TaskManagerWorkerTask = null; TaskQueueDrained?.Invoke(this, new EventArgs()); Logger.LogDebug("Task Queue drained"); }); //TaskManagerWorkerTask.Tag(WorkspaceId, true); }