1

I have a structure like this.

Parent-----Children1
|
-------Children2
         |
          -------Children2.1
         |
         --------Children2.2

How can I loop into this tree and execute Parent in new Task, then when is finished Children1 and Children2 parallel, then when is finished Children2.1 and Children2.2 also parallel? So the order of executing is like in graph.

Theodor Zoulias
  • 34,835
  • 7
  • 69
  • 104
Florim Maxhuni
  • 1,421
  • 1
  • 17
  • 35
  • Related: [Parallel tree traversal in C#](https://stackoverflow.com/questions/7099703/parallel-tree-traversal-in-c-sharp). The other question doesn't require the traversal to be hierarchical, so it's not a duplicate. – Theodor Zoulias Apr 19 '23 at 14:28

3 Answers3

2

use Parallel.Foreach for running task on all childs, and then in the end call all childs subchild:

void run()
{
   do action on parent;
   DoTasks(parent);
}

void DoTasks(Node node)
{
  if (node.Childs == null) return;

  Parallel.Foreach(node.Childs, child => {do action})

  foreach(var child in node.Childs)
  {
    DoTasks(child);
  }
}

parallel.foreach waits untill all tasks finished.

Saeed Amiri
  • 22,252
  • 5
  • 45
  • 83
  • Thanks that did the work, one more question if i nead to implement cancelation example if I cancel Parent then all childrens will be cancel. how can i do that. Sorry for my bad english. THanks in advance. – Florim Maxhuni Dec 22 '10 at 21:22
  • @Florim Maxhuni, if the cancellation is within first Foreach loop, I think there is no normal way, but in second foreach node you can check node.Canceled, if is true, do not run DoTasks – Saeed Amiri Dec 23 '10 at 09:26
0

If you are looking for a bit more robust code, take a look at the following project of mine on github:

Parallel async TreeWalker

It contains a simple .Net tool for discovering a huge tree structure efficiently (without consuming much resources) and still parallel, without a bottleneck. It was designed to deal with async calls in mind.

An example for discovering a directory structure in the file system:

await TreeWalker.WalkAsync(root, new TreeWalkerOptions
{
  MaxDegreeOfParallelism = 5,
  ProcessElementAsync = async (element) =>
  {
      // this is the action that is executed on every element
      var el = element as FileSystemElement;
      var path = el.Path;
      var isDirectory = el.IsDirectory;

      await DoStuffAsync(el);
  }
});

This single method call makes the plugin discover the full tree structure and lets you execute an action on every element.

The FileSystemElement class above is a built-in sample implementation of the ITreeElement interface, you can create your own class for your structure (or implement the very simple interface in your existing class).

Miklós Tóth
  • 1,490
  • 13
  • 19
0

Try TreeifyTask GithubLinkHere

You can create root and sub tasks those can be executed in an order sequentially or in parallel. The handle is from the root node.

Usage: Create root task and child tasks

ITaskNode rootTask = new TaskNode("root");

ITaskNode childTask_1 = new TaskNode("Task-1");
ITaskNode childTask_2 = new TaskNode("Task-2");

rootTask.AddChild(childTask_1);
rootTask.AddChild(childTask_2);

Usage: Set actions to child tasks

childTask_1.SetAction(async (reporter, cancellationToken) => {
    // Simple delay function.
    reporter.ReportProgress(TaskStatus.InProgress, 10, "Started...");
    await Task.Delay(1000);
    reporter.ReportProgress(TaskStatus.InProgress, 100, "Finished...");
});

childTask_2.SetAction(async (reporter, cancellationToken) => {
    // Simple delay function.
    reporter.ReportProgress(TaskStatus.InProgress, 5, "Started...");
    await Task.Delay(2500);
    reporter.ReportProgress(TaskStatus.InProgress, 100, "Finished...");
});

Usage: Subscribe to Root node

// Before starting the execution, you need to subscribe for progress report.
rootTask.Reporting += (object sender, ProgressReportingEventArgs eventArgs) => {
    eventArgs.ProgressValue; // -> this will represent the overall progress
};

Usage: Start execution

// Create and pass the cancellation token
var tokenSource = new CancellationTokenSource();
var token = tokenSource.Token;

// Start the execution concurrently
rootTask.ExecuteConcurrently(cancellationToken: token, throwOnError: true);


// OR

// Start the execution in series
rootTask.ExecuteInSeries(cancellationToken: token, throwOnError: true);

Error handling is easy as Execute* methods throw exception with entire tree structure. Here the ID plays a role and it helps to to debug quickly.

Gokul E
  • 1,356
  • 2
  • 13
  • 28