2014-12-29 12 views
5

Dato che stavo capendo il Task nel contesto dell'attività annidata, non lo capisco davvero- Perché la terza stampa prima della seconda stampa?Task.ContinueWith() attività principale non attende l'operazione figlio per terminare

Anche se, ho usato Task.WaitAll(t), esso stampa terza linea prima secondo linea.

Codice:

public static void Main() 
     { 

      Task t = new Task(
       () => 
       { 
        Thread.Sleep(2000); 
        Console.WriteLine("1st print..."); 
       }); 
      t.ContinueWith(
       x => 
       { 
        Thread.Sleep(2000); 
        Console.WriteLine("2nd print..."); 
       }, 
       TaskContinuationOptions.OnlyOnRanToCompletion); 

      t.Start(); 
      Task.WaitAll(t); 

      Console.WriteLine("3rd print..."); 
      Console.Read(); 

} 

uscita:

enter image description here

+0

Si producono lo stesso risultato, anche se uso 'TaskContinuationOptions.AttachedToParent' con l'opzione di task figlio. – nunu

+0

@Andrey Certo, abbiamo la domanda duplicata, ma la risposta di questa domanda duplicata si basa sulla creazione di una serie di attività Task [] che è la soluzione che conosco. Ma voglio sapere la risposta senza creare l'array Task []. – nunu

+0

Voglio usare la mia macchina per andare in posti senza gas, ma non si muoverà! – Jcl

risposta

5

è necessario attendere per la prosecuzione anche:

Task t2 = t.ContinueWith(/* .. */); 
Task.WaitAll(new [] { t, t2 }); 
+0

Grazie @Jcl! MA, non voglio creare più attività. Voglio gestire questo con un singolo compito. Naturalmente, possiamo creare attività nidificate in attività di un genitore come attività secondarie, ma NON attività completamente diverse. – nunu

+3

Stai usando 'ContinueWith', quindi stai già creando una seconda attività ... non stai semplicemente memorizzando il risultato della funzione' ContinueWith', ma ciò non significa che l'attività non sia stata creata. – Jcl

2

Hai aspettato solo per t, non per la sua continuazione. Ecco perché quella continuazione verrà eseguita in futuro. Se non fosse per lo Console.Read, potrebbe non funzionare mai prima che il processo sia terminato.

Task.WaitAll(t) equivale a t.Wait() (che è invece consigliabile utilizzare perché è più idiomatico).

Aspettare tutte le continuazioni (forse in modo ricorsivo) potrebbe comportare comportamenti non intuitivi e avere effetti non locali. Parti remote del programma potrebbero influenzare il tuo codice.

+0

Grazie a @usr! Ora la domanda è: come potrei aspettare che l'operazione nidificata finisca? – nunu

+0

Memorizza l'attività da qualche parte e attendi anche su di essa. – usr

0

Si presuppone che dovrebbe attendere le attività secondarie, ma non esiste una base per formulare tali ipotesi. Da MSDN:

Task.WaitAll: attende che tutti gli oggetti Task forniti completino l'esecuzione .

E fa esattamente quello che dice. ContinueWith non modifica la lunghezza dell'attività originale, non si allunga. Si esegue subito dopo.

Problemi correlati