2015-03-03 7 views
10

Sto chiamando un metodo asincrono all'interno della mia applicazione console. Non voglio che l'app si interrompa poco dopo il suo avvio, cioè prima che vengano completate le attività attendibili. Sembra che io possa fare questo:Perché è necessario AsyncContext quando si utilizza async/await con un'applicazione console?

internal static void Main(string[] args) 
{ 
    try 
    { 
     Task.WaitAll(DoThisAsync()); 
    } 
    catch (Exception ex) 
    { 
     Console.Error.WriteLine(ex); 
     throw; 
    } 
} 

internal static async Task DoThisAsync() 
{ 
    //... 
} 

Ma secondo Stephen Cleary's article sembra che non posso fare questo e invece creare una sorta di contesto per l'asincrona per tornare quando è fatto (per esempio AsyncContext).

Il codice sopra funziona, tuttavia, e restituisce il thread principale dopo Task.WaitAll(DoThisAsync());, quindi perché è necessario utilizzare un contesto personalizzato?

+0

Forse questo succede quando usi threadpool. I thread di Threadpool sono thread in background e solo il thread principale è in primo piano. Le applicazioni UI avranno un ciclo principale che non consente loro di uscire prima che succeda qualcosa, e le applicazioni di console di solito non hanno questo ciclo. Quindi, se non blocchi il tuo thread principale in attesa di qualcosa, la tua applicazione uscirà e il lavoro che stavi facendo su un threadpool non funzionerà più. Non sono sicuro però. – Spo1ler

+0

Come menzionato da @StephenCleary, è solo una preferenza. Non importa quanto blocchi il thread, devi solo essere consapevole che se non riesci a gestire quel thread, l'applicazione uscirà (anche se gli altri thread non sono stati eseguiti) – Brandon

+0

@Brandon Bene, * * questioni. Funzionano in modo diverso, ma è ovviamente possibile scrivere programmi di lavoro usando entrambi gli approcci. – Servy

risposta

18

Non richiesto; è solo la mia preferenza

Puoi sincrono bloccare su un compito all'interno Main (usando Wait/Result/WaitAll). La semantica è leggermente diversa; in particolare, se il codice asincrono fallisce, allora/avvolgerà l'eccezione in uno AggregateException, mentre lo AsyncContext no.

Inoltre, AsyncContext tratta specificamente il filo principale; invece di inviare continuazioni al pool di thread, le invierà di nuovo al thread principale (per impostazione predefinita, è sempre possibile utilizzare ConfigureAwait(false) per evitare ciò). Lo trovo utile se sto scrivendo un'app console "proof of concept", perché AsyncContext si comporta in modo molto simile ai contesti dell'interfaccia utente.

Ma alla fine, è solo una questione di preferenza.

+0

Dovrò ricordare lo scopo principale di avere AsyncContext per simulare un'interfaccia utente. –

+0

Perché [AsyncContext] (https://github.com/StephenCleary/AsyncEx/tree/master/Source/Nito.AsyncEx%20 (NET45% 2C% 20Win8% 2C% 20WP8% 2C% 20WPA81) richiede così tanto codice se tutto quello che stai facendo è prevenire l''AggregateException'? Vedo un TaskScheduler, TaskQueue (BlockingQueue), TaskFactory e AsyncContextSynchronizationContext. Vedo un AsyncContextThread che dice che esegue le azioni per AsyncContext. Credo che il mio punto sia che sembra che ci sia molto da fare qui, ma non ho trovato una buona opinione su ciò che sta realmente accadendo. Non ho tempo per cercare di decifrare cosa sta succedendo. – crush

+0

Hai un articolo sul blog da qualche parte che spiega cosa sta succedendo sotto il cofano? Tutto quello che trovo è che '.Result' e' .Wait() 'sono cattivi, e dovrei usare il tuo' AsyncContext' invece. Perché? Cosa fa 'AsyncContext' in modo diverso che lo rende una scelta migliore? Mi sembra che stai pianificando le attività da eseguire su un thread in background, in modo che se il thread principale termina, continueranno a funzionare fino al completamento? È corretto? – crush

Problemi correlati