private void PerformTasks(TasksState <T> tasksState)
        {
            T task;

            lock (tasksState)
            {
                if (!tasksState.TasksToDo.Any() && !tasksState.TasksInProgress.Any())
                {
                    return;
                }

                task = FindTaskToDo(tasksState);
            }

            if (task == null)
            {
                if (tasksState.TasksInProgress.Any())
                {
                    return;
                }

                throw new Exception("There are some tasks with dependencies that can't be satisfied.");
            }

            MoveTaskToInProgress(tasksState, task);
            Task.Run(() => PerformTasks(tasksState));

            PerformTaskAndTheTasksDependentOnIt(tasksState, task);
        }
 private static void MoveTaskToDone(TasksState <T> tasksState, T task)
 {
     lock (tasksState)
     {
         tasksState.TasksInProgress.Remove(task);
         tasksState.DoneTasks.Add(task);
     }
 }
        public void PerformTasks(IEnumerable <T> tasks)
        {
            var tasksState = new TasksState <T>
            {
                DoneTasks       = new HashSet <T>(),
                TasksToDo       = new List <T>(tasks),
                TasksInProgress = new HashSet <T>()
            };

            PerformTasks(tasksState);
        }
        private T FindTaskToDo(TasksState <T> tasksState)
        {
            foreach (var task in tasksState.TasksToDo)
            {
                var dependencies = _getDependenciesFunction(task);
                if (dependencies == null || dependencies.All(d => tasksState.DoneTasks.Contains(d)))
                {
                    return(task);
                }
            }

            return(null);
        }
        private void PerformTaskAndTheTasksDependentOnIt(TasksState <T> tasksState, T task)
        {
            _performTaskFunction(task).ContinueWith(taskResult =>
            {
                if (!taskResult.Result)
                {
                    return;
                }

                MoveTaskToDone(tasksState, task);
                PerformTasks(tasksState);
            }).Wait();
        }