The following code shows a binary tree.
public class Tree<T>
{
public T Data { get; set; }
public Tree<T> Left { get; set; }
public Tree<T> Right { get; set; }
}
If you want to perform an
action on each data value in the tree, you need to visit each node.
This is known as walking the tree, which is a naturally recursive
operation. Here’s an example that uses sequential code.
static void SequentialWalk<T>(Tree<T> tree, Action<T> action)
{
if (tree == null) return;
action(tree.Data);
SequentialWalk(tree.Left, action);
SequentialWalk(tree.Right, action);
}
You can also use parallel tasks to walk the tree.
static void ParallelWalk<T>(Tree<T> tree, Action<T> action)
{
if (tree == null) return;
var t1 = Task.Factory.StartNew(
() => action(tree.Data));
var t2 = Task.Factory.StartNew(
() => ParallelWalk(tree.Left, action));
var t3 = Task.Factory.StartNew(
() => ParallelWalk(tree.Right, action));
Task.WaitAll(t1, t2, t3);
}
You don’t need to create a new
task to walk the right side of the tree. If you want, you can use the
current task; however, using tasks for both the left and right walks
makes sure that exceptions that are thrown by either will be observed.
When you use dynamic
task parallelism to perform a tree walk, you no longer visit nodes in a
fully predictable order.
Note:
Dynamic task parallelism results in a less predictable order of execution than sequential code.