2015-08-24 9 views
9

Quali sono le differenze tra questi due metodi che sembrano fare la stessa cosa? Può essere fatto anche con async/attendi?C# Differenze tra Risultato e Continua con

public Task<int> TaskMaxAsync1 (Task<int>[] my_ints) 
{ 
    return Task.WhenAll(my_ints) 
    .ContinueWith (x => x.Result.Where (i => i%2 != 0).Max()) ; 
} 

public Task<int> TaskMaxAsync2 (Task<int>[] my_ints) 
{ 
    var numbers = Task.WhenAll(my_ints).Result ; 
    return Task.FromResult(numbers.Where(i => i%2 != 0).Max()) ; 
} 
+1

Una differenza sarebbe che quella che utilizza '.Result' è incline a deadlocking - http://stackoverflow.com/questions/17248680/await-works- ma-calling-task-result-hang-deadlocks –

+0

@ LasseV.Karlsen Entrambi usano .Result – TheLethalCoder

+5

Agh, sì, ok, fammi riformulare. Quello che usa '.Result' al di fuori di' ContinueWith' (es.il secondo) è soggetto a deadlocking. L'unico posto in cui è sicuro leggere ".Result" deriva da un'attività che è stata completata. La lettura di '.Result' da un'attività che non è stata ancora completata potrebbe bloccarsi. –

risposta

6

Differenze tra Risultato e ContinueWith

Result saranno sincrono bloccare fino a quando l'operazione viene completata, e sarà avvolgere eccezioni in un AggregateException.

ContinueWith registrerà un callback con l'attività e invocherà quella richiamata al termine dell'attività.

Per il codice asincrono, entrambi Result e ContinueWith devono essere sostituiti da await.

Può essere eseguito anche con asincrono/attendi?

Certo, in questo modo:

public async Task<int> MaxAsync(Task<int>[] my_ints) 
{ 
    int[] ints = await Task.WhenAll(my_ints); 
    return ints.Where(i => i % 2 != 0).Max(); 
} 
7

Quali sono le differenze tra questi due metodi che sembra fare la stessa cosa ?

La differenza è che il primo restituisce un compito caldo al chiamante, mentre i blocchi sincronia ultimi, poi ri-avvolge il risultato in un Task utilizzando Task.FromResult. Quest'ultimo è anche un caso comune per deadlock, se si sta eseguendo all'interno di un ambiente che ha un SynchronizationContext personalizzato.

Può essere eseguito anche con asincrono/attendi?

Sì, può:

public async Task<int> MaxAsync(Task<int>[] myInts) 
{ 
    int[] results = await Task.WhenAll(myInts); 
    return results.Max(i => i % 2 != 0 ? i : (int?)null) ?? 0; 
} 
3

task0.Result sarà sincrono bloccare e attendere task0 per completare, mentre task1.ContinueWith non aspetterà task1 per completare, ma restituisce un nuovo Task (che sarà eseguito quando task1 Completa) subito.

Quindi, i due metodi nell'esempio non si comportano allo stesso modo. Nel secondo metodo, se la serie my_ints non è stata completata per il passaggio al metodo WhenAll, lo .Result bloccherà in modo sincrono il thread chiamante per tutto il tempo necessario per completare tutte le attività entro my_ints e se alcune di esse generano eccezione, i tiri TaskMaxAsync2.

Tuttavia, il primo metodo restituirà immediatamente anche my_ints non finirebbe mai o genererebbe un'eccezione.