How to wait for all tasks (created task and subtask) without using TaskCreationOptions.AttachedToParent

I will need to create parallel software that will create several Task, and each Task can generate another task (which can also generate another task, ...).

I need the call to the method that started the task to be blocked: there is no return ADDITIONAL PROGRAM OF ALL tasks and subtasks.

I know this property TaskCreationOptions.AttachedToParent, but I think it does not fit:

The server will have at least 8 cores, and each task will create 2-3 subtasks, so if I set the parameter AttachedToParent, I have the impression that the second subtask will not start until the three tasks of the first subtask end. Therefore, I will have limited multitasking.

So, with this process tree:

enter image description here

I got the impression that if I set the AttachedToParent property every time I start the thread, B does not end until the completion of E, F, G, so C starts until the end of B, and instead I will only have 3 out of 8 asset flows. which i can have.

If I do not set the AttachedToParent property, A will complete very quickly and return.

So, how could I do to always use my 8 cores if I do not set this parameter?

+5
3

TaskCreationOptions.AttachedToParent , . , E, F G AttachedToParent, B , . , .

( ).

+2

Me.Name, AttachedToParent . , .

- , Task.WaitAll(), , .

Task.WaitAll() , Task. , .Net 4.5, Task.WhenAll(), Task, , Task.

+2

You could TaskFactorycreate parameters, as in this example:

Task parent = new Task(() => { 
var cts = new CancellationTokenSource(); 
var tf = new TaskFactory<Int32>(cts.Token,  
                                        TaskCreationOptions.AttachedToParent,  
                                        TaskContinuationOptions.ExecuteSynchronously,  
TaskScheduler.Default); 

 // This tasks creates and starts 3 child tasks 
 var childTasks = new[] { 
       tf.StartNew(() => Sum(cts.Token, 10000)), 
       tf.StartNew(() => Sum(cts.Token, 20000)), 
       tf.StartNew(() => Sum(cts.Token, Int32.MaxValue))  // Too big, throws Overflow
 }; 

// If any of the child tasks throw, cancel the rest of them 
for (Int32 task = 0; task <childTasks.Length; task++) 
  childTasks[task].ContinueWith( 
     t => cts.Cancel(), TaskContinuationOptions.OnlyOnFaulted); 

// When all children are done, get the maximum value returned from the  
// non-faulting/canceled tasks. Then pass the maximum value to another  
// task which displays the maximum result 
tf.ContinueWhenAll( 
   childTasks,  
   completedTasks => completedTasks.Where( 
     t => !t.IsFaulted && !t.IsCanceled).Max(t => t.Result), CancellationToken.None) 
   .ContinueWith(t =>Console.WriteLine("The maximum is: " + t.Result), 
      TaskContinuationOptions.ExecuteSynchronously); 
}); 

// When the children are done, show any unhandled exceptions too 
parent.ContinueWith(p => { 
    // I put all this text in a StringBuilder and call Console.WriteLine just once  
    // because this task could execute concurrently with the task above & I don't  
    // want the tasks' output interspersed 
    StringBuildersb = new StringBuilder( 
                      "The following exception(s) occurred:" + Environment.NewLine); 

    foreach (var e in p.Exception.Flatten().InnerExceptions)  
         sb.AppendLine("   "+ e.GetType().ToString()); 

    Console.WriteLine(sb.ToString()); 
  }, TaskContinuationOptions.OnlyOnFaulted);

  // Start the parent Task so it can start its children 
  parent.Start();
+1
source

All Articles