Florim Maxhuni
Florim Maxhuni

Reputation: 1421

Parallel Task for Tree structure

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.

Upvotes: 1

Views: 1526

Answers (3)

Gokul E
Gokul E

Reputation: 1386

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.

Upvotes: 0

Miklós Tóth
Miklós Tóth

Reputation: 1511

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).

Upvotes: 0

Saeed Amiri
Saeed Amiri

Reputation: 22565

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.

Upvotes: 2

Related Questions