This problem can be solved by implementing the task scheduler.
No matter what I do, it uses a scheduler with a pending job queue and a current list of tasks. The tasks will be placed in the waiting tasks in the order of receipt, and the scheduler will be responsible for checking whether the next waiting task is allowed to perform, looking at the tasks currently being performed and moving from the waiting task and launching it accordingly.
You will need a callback mechanism to signal the completion of tasks and should be removed from the execution list by the scheduler:
public abstract class Job { public event EventHandler<MyFinishedJobEventArgs> JobFinished; public void Run() { var e = new MyFinishedJobEventArgs(...); OnRunJob(e); if (JobFinished != null) JobFinished(this, e); } protected abstract void OnRunJob(MyFinsishedJobEventArgs e);
The hard part here, of course, is ensuring proper synchronization with decent performance.
Agreeing with the rules that determine which jobs can be started or not, if all of them are of the JobX type, which cannot be executed during the work of JobY and JobZ, then this can be easily described in the scheduler, tracking incompatibility of jobs; I would use Dictionary<Type, IEnumerable<Type>>
void RegisterIncompatibility(Job job, IEnumerable<Job> incompatibleJobs) { incompatibilities.Add(job.GetType(), incompatibleJobs.Select(j => j.GetType()); }
Now the scheduler should simply check before starting the next task for any current incompatibility:
private bool canRunJob(Job job) { //omitted null checks, contains key check, etc. if (executingJobs.Any(j => incompatible.Contains(j.GetType()))) return false; return true; }
This should be simple enough if you keep the order of execution. That is, the first task assigned is the first task that will be executed, and it will block all other pending tasks until it is allowed to work.
If you need to skip tasks that are currently not allowed to run and perform other pending tasks until the conditions are met, everything will start to get hairy.