2013-04-08 9 views
5

Sto cercando di utilizzare Task.ContinueWith con TaskContinuationOptions.AttachedToParent per eseguire un'attività di continuazione, ad es.Task.ContinueWith e TaskContinuationOptions.AttachedToParent

Task outerTask = new Task(() => Console.WriteLine("Outer")); 
Task innerTask = outerTask.ContinueWith(t => 
    { 
     Thread.Sleep(500); 
     Console.WriteLine("Inner"); 
    }, 
    TaskContinuationOptions.AttachedToParent | TaskContinuationOptions.OnlyOnRanToCompletion); 
outerTask.Start(); 
outerTask.Wait(); 
Console.WriteLine("Outer done"); 

L'output di questo codice è

Outer 
Outer done 
Inner 

ma quello che mi aspettavo/cercare di raggiungere è

Outer 
Inner 
Outer done 

E 'possibile utilizzare AttachedToParent per bloccare un completamento delle attività esterna, o è AttachedToParent efficace solo per le attività annidate?

Edit:

Quello che sto cercando di realizzare è una che voglio eseguire un'attività continuazione quando outerTask è completata con successo. Voglio outerTask propagare eccezioni da innerTask al chiamante, senza dover affrontare innerTask. Se l'errore outerTask non riesce, è sufficiente lanciare immediatamente l'eccezione (su outerTask.Wait() senza chiamare innerTask).

+1

innerTask non è un'attività interna, ma un'attività che viene eseguita dopo il completamento di outerTask. Questo è il punto di "ContinueWith". – JustAnotherUserYouMayKnow

+0

@JustAnotherUserYouMayKnow: Quindi 'AttachedToParent' viene semplicemente ignorato da' ContinueWith'? – larsmoa

+4

In questo caso viene ignorato. Quando crei il tuo compito in un'altra attività, allora hai un compito "interiore" in cui è collegato a un genitore. – JustAnotherUserYouMayKnow

risposta

7

Non ci sono attività padre-figlio nel codice.
si potrebbe desiderare di controllare che cosa è il compito interno o bambino, che può essere di due tipi:

  • detached child task or nested task, vale a dire compito parallelo creato withing il delegato di un altro compito senza una connessione a al compito-creatore
  • attached child task or simply child task, nel qual caso se un compito bambino genera un'eccezione che è altrimenti non gestita, che viene catturato dal genitore e rilanciati

    Aggiornamento

    "E 'possibile utilizzare AttachedToParent per bloccare un compito completamento esterno ..."

    "Voglio eseguire un'attività continuazione quando outerTask è completato con successo"

    CiCiting dal ultimo:

    • "Un'attività padre non terminerà l'esecuzione fino al completamento di tutte le attività figlio, normalmente o con eccezioni. Il genitore esegue essenzialmente un comando di attesa per tutti i suoi figli
    • Se un'attività secondaria genera un'eccezione che altrimenti non è gestita, viene catturata dal genitore e retrocessa.È possibile che molte attività figlio generino un'eccezione. Tutti saranno combinati con qualsiasi eccezione non gestita lanciata dalla casa madre direttamente in un unico AggregateException "

Per il vostro caso, in cui non ci sono attività padre-figlio, leggere Handling Exceptions with Continuations:.

"È importante capire che non esiste alcuna relazione tra gli antecedenti e le continuazioni , ad eccezione di quella che controlla la pianificazione . Nello specifico, le eccezioni generate da un'attività non sono propagate alle attività di continuazione collegate. Ciò significa che lo deve verificare le eccezioni in tutte le attività eseguite. La soluzione più semplice è quella di aspettare per tutte le attività che può errore di completa e circondare il metodo Wait con un blocco try/catch"

ci sono anche gli esempi di codice di cattura-moltiplicazione eccezioni nel previsto dai collegamenti articoli

Aggiornamento:

Edit:

Quello che sto cercando di raggiungere è un che voglio eseguire un'attività di continuazione quando outerTask è stato completato con successo. Voglio outerTask su propagare eccezioni da innerTask al chiamante, senza dover fare uso di innerTask con . Se outerTask fallisce, dovrebbe semplicemente lanciare immediatamente l'eccezione (su outerTask.Wait() senza chiamare innerTask).

Probabilmente, avete già visto l'esempio di codice da MSDN articolo Task.ContinueWith Method (Func, CancellationToken, TaskContinuationOptions, TaskScheduler), che illustra come impedire/seguire compito continuazione se antecedente fallisce/succedes (o viceversa, 4 combinazioni). Ma questo non è un compito genitore-figlio, ma un processo di proseguimento antecedente, quindi non vi è alcun contenimento o collegamento per la propagazione delle eccezioni in entrambe le direzioni.

In caso di attività figlio-genitore, è impossibile impedire le attività figlio dopo che sono già state avviate e solo dopo che un genitore ha avuto esito negativo (o ovviamente cancella un genitore da figlio).

1

per ottenere ciò che si desidera, modificare la riga

outerTask.Wait(); 

a

innerTask.Wait(); 

appena outertask completa, l'esecuzione passa l'attesa e scrive 'esterna fatta', mentre il compito interna è acceso Thread.Sleep.

+0

Il punto qui è che sta provando a fare in modo che il compito secondario estenda il tempo che il tempo genitore impiega a considerarsi "fatto", in modo che possa, ad esempio, avere un metodo che accetti un "compito", aggiungere continuazioni, e fare in modo che l'operazione passata richieda più tempo. Altre sezioni di codice non saprebbero del bambino. – Servy

+1

+1 la risposta di @ Steve risponde correttamente a "ma quello che mi aspettavo/cerco di ottenere è Outer-> Inner-> Outer done" ordine di output. È un gioco di ipotesi se l'OP sta cercando di ottenere COSA o COME –

-1

L'atto di aggiungere una continuazione a un'attività non cambierà mai quando la prima attività è considerata "completata". Non c'è modo di forzare il genitore a non essere contrassegnato come "completato" finché non viene eseguita tutta (o anche una particolare) continuazione.

Problemi correlati