Introduction
When you have multiple tasks to perform, it can really help if you can do some of them in parallel. However, when they are dependent on each other, it sometimes becomes a real pain to manage which tasks can be performed in parallel, and sometimes programmers prefer to give up and perform the tasks sequentially to avoid this pain. I didn't find any library that handles this problem, so I decided to write my own (DependentTaskRunner ) to make life a little bit easier. In this tip, I will explain how to use this library on a very simple example. The solution is pretty much scalable for more complex cases as well.
Using the Code
Open a new Visual Studio console application and add the DependentTaskRunner
nuget package to it:
Install It:
In Program.cs file, add this using
:
using DependentTaskRunner;
Create a new class called MyTask
:
public class MyTask
{
public MyTask[] Dependencies { get; set; }
public Func<bool> Perform { get; set; }
}
Write the taskRunner
initialization code in the Main
function:
var taskRunner = new TaskRunner<MyTask>(t => t.Dependencies, t => Task.Run(() => t.Perform()));
Now, we need to write the code that performs the tasks.
Suppose you want to perform 3 tasks: A, B, C.
C can be performed only after A and B are finished:
Each task is represented as a function that returns a boolean value that indicates whether the task finished successfully or failed:
private static bool RunA()
{
Console.WriteLine(DateTime.Now + " A Started");
Thread.Sleep(2000);
Console.WriteLine(DateTime.Now + " A Finished");
return true;
}
private static bool RunB()
{
Console.WriteLine(DateTime.Now + " B Started");
Thread.Sleep(3000);
Console.WriteLine(DateTime.Now + " B Finished");
return true;
}
private static bool RunC()
{
Console.WriteLine(DateTime.Now + " C Started");
Thread.Sleep(4000);
Console.WriteLine(DateTime.Now + " C Finished");
return true;
}
Now we need to create the task
objects in the Main
function:
var taskA = new MyTask { Perform = RunA };
var taskB = new MyTask { Perform = RunB };
var taskC = new MyTask { Dependencies = new[] { taskA, taskB }, Perform = RunC };
And make the tasks start running:
taskRunner.PerformTasks(new[] { taskA, taskB, taskC });
And this is it.
Now we can run the code:
We can see that A and B were performed in parallel and C is performed only after A and B are both finished.
The whole code should look like this now:
class Program
{
static void Main(string[] args)
{
var taskRunner = new TaskRunner<MyTask>
(t => t.Dependencies, t => Task.Run(() => t.Perform()));
var taskA = new MyTask { Perform = RunA };
var taskB = new MyTask { Perform = RunB };
var taskC = new MyTask { Dependencies = new[] { taskA, taskB }, Perform = RunC };
taskRunner.PerformTasks(new[] { taskA, taskB, taskC });
Console.ReadLine();
}
private static bool RunA()
{
Console.WriteLine(DateTime.Now + " A Started");
Thread.Sleep(2000);
Console.WriteLine(DateTime.Now + " A Finished");
return true;
}
private static bool RunB()
{
Console.WriteLine(DateTime.Now + " B Started");
Thread.Sleep(3000);
Console.WriteLine(DateTime.Now + " B Finished");
return true;
}
private static bool RunC()
{
Console.WriteLine(DateTime.Now + " C Started");
Thread.Sleep(4000);
Console.WriteLine(DateTime.Now + " C Finished");
return true;
}
public class MyTask
{
public MyTask[] Dependencies { get; set; }
public Func<bool> Perform { get; set; }
}
}
Pay attention that if a function of a task returns false
, the tasks that depends on it will never be performed, for example if we will change the RunA
function:
private static bool RunA()
{
Console.WriteLine(DateTime.Now + " A Started");
Thread.Sleep(2000);
Console.WriteLine(DateTime.Now + " A Finished");
return false;
}
This is the result we will get:
The C Task is never performed because the A task failed.
I showed only one very basic way to use the library, if you would like to use Async
/Await
, you can find an example here. There are more examples to using the library here.
What's Next?
My code is actually open source and can be found here.
If you want some explanation about the code, I will be glad to write another article with explanation.
Feel free to write any suggestions or issues you have found.
Useful Links