5

Tendré que crear un software concurrente que cree varias Tareas, y cada Tarea podría generar otra tarea (que también podría generar otra Tarea, .. .).Cómo esperar en todas las tareas (tarea creada y subtarea) sin usar TaskCreationOptions.AttachedToParent

Necesito que la llamada al método que la tarea de inicio esté bloqueando: ninguna devolución ANTES de que se completen todas las tareas y subtareas.

Sé que hay esta TaskCreationOptions.AttachedToParent propiedad, pero creo que no encaja:

el servidor va a tener algo como 8 núcleos por lo menos, y cada tarea creará 2-3 subtarea, así que si me puse el AttachedToParent opción, tengo la impresión de que la segunda subtarea no comenzará antes de que finalicen las tres tareas de la primera subtarea. Así que tendré una multitarea limitada aquí.

Así que con este proceso de árbol:

enter image description here

tengo la impresión de que si fijo AttachedToParent cada propiedad lanzo un hilo, no se hayan terminado antes extremos E, F, G B, por lo C comenzará antes de que B finalice, y tendré solo 3 hilos activos en lugar de los 8 que puedo tener.

Si no pongo la propiedad AttachedToParent, A terminará muy rápido y volverá.

Entonces, ¿cómo podría hacer para asegurarme de que siempre he utilizado mis 8 núcleos si no configuro esta opción?

+3

No confíe en las impresiones. O búsquelo en la documentación o pruébelo usted mismo. – svick

Respuesta

2

El TaskCreationOptions.AttachedToParent no impide que otras subtareas se inicien, sino que evita que se cierre la tarea principal. Entonces, cuando E, F y G se inician con AttachedToParent, B no se marca como terminado hasta que los tres terminen. Por lo tanto, debería hacer lo que quiera.

source (en la respuesta aceptada).

2

Como Me.Name mencionado, AttachedToParent no se comporta de acuerdo con sus impresiones. Creo que es una buena opción en este caso.

Pero si no desea utilizarlo por cualquier motivo, puede esperar a que todas las tareas secundarias terminen en Task.WaitAll(). Aunque significa que debes tenerlos todos en una colección.

Task.WaitAll() bloquea el hilo actual hasta que se completen todos los Task s. Si no quiere eso y está en .Net 4.5, puede usar Task.WhenAll(), que devolverá un único Task que terminará cuando finalice todo el Task dado.

1

Usted podría crear opciones que TaskFactory como en este ejemplo:

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(); 
Cuestiones relacionadas