2014-07-01 10 views
9

C'è un modo per utilizzare il Task-based Asynchronous Pattern (TAP) in .NET 4.0 senza il await e async parole chiave? (Lo chiedo perché siamo bloccati in C# 4.0.)Utilizzare Task-based del modello asincrono (TAP) con .NET 4.0 e C# 4.0

Inoltre, c'è un esempio di utilizzo TAP con WCF con .NET 4.0?

+1

solo per essere sicuri di non perdere su nulla e non confondere i numeri di versione # .NET e C: se _potete_ compila il C# 5 codice che utilizza 'attendono/async' ad un NET 4.0 assembly. Devi solo fare riferimento al pacchetto di targeting asincrono (è su nuget) per farlo funzionare correttamente. Se per qualche motivo sei bloccato con il compilatore C# 4, allora vedi le risposte alla tua domanda, che è sì. – jods

risposta

0

Senza l'async/attendono parole chiave non sarà in grado di utilizzare la facilità fornito dal compilatore di utilizzare il nuovo modello. Tuttavia è possibile sfruttare il parallelismo basato Task utilizzando Task Parallel Library (TPL) in .NET 4 framework

+0

Si prega di indicare il motivo del voto negativo. Posso sicuramente andare avanti e cancellare la mia risposta se mi sto sbagliando ... – Adil

+1

Ho cambiato il downvote. Ora la risposta è giusta. Se utilizzi TPL per implementare TAP "manualmente", devi completare l'attività risultante quando l'operazione asincrona rappresentata viene completata tramite "Continuazioni", ovvero tutto ciò che attende è comunque lo stesso ... – MoonKnight

+0

@Killercam Sì, l'ho capito, era un po ' fuorviante ... risposta aggiornata. – Adil

7

Non è necessario asincrona/attendono. Le parole chiave possono essere

ContinueWith e TaskScheduler.FromCurrentSynchronizationContext

Task.Factory.StartNew(() => { return "test"; }) 
      .ContinueWith(task => { this.textBox1.Text = task.Result; }, 
          CancellationToken.None, 
          TaskContinuationOptions.None, 
          TaskScheduler.FromCurrentSynchronizationContext()); 

Questo è approssimativamente uguale a

var str = await SomeFuncAsync() //returning "test"; 
this.textBox1.Text = str; 
10

Sì, è possibile. Il TAP è solo una ragionevole formalizzazione delle migliori pratiche quando si lavora con il codice asincrono. In pratica un metodo TAP

  1. Restituisce un 'caldo' (in esecuzione) o TaskTask<TResult>.
  2. ha un 'Async' suffisso (ad esempio SomeMethodAsync(...)).
  3. È sovraccarico per accettare un token di cancellazione.
  4. ritorna rapidamente al chiamante (con piccolo fase di inizializzazione).
  5. Non lega una discussione se I/O è vincolato.

Così, un esempio potrebbe essere

private Task SomeMethodAsync(CancellationToken token) 
{ 
    return Task.Factory.StartNew(() => 
    { 
     // Do something... 
    }, token); 
} 

uso del metodo e collegare continuazione che utilizza il contesto di sincronizzazione UI.

private void SomeOtherMethod() 
{ 
    var tokenSource = new CancellationTokenSource(); 
    CancellationToken token = tokenSource.Token; 
    TaskScheduler scheduler = TaskScheduler.FromCurrentSynchronizationContext() 

    // Options 1. 
    Task t = SomeMethodAsync(token); 
    Task c = t.ContinueWith(ant => 
     { 
      /* Do something and check exceptions */ 
     }, CancellationToken.None, 
      TaskContinuationOptions.None, 
      scheduler); 

    // Options 2. 
    SomeMethodAsync(token).ContinueWith(ant => 
     { 
      /* Do something and check exceptions */ 
     }, CancellationToken.None, 
      TaskContinuationOptions.None, 
      scheduler); 
} 

o farlo tutto in una volta sola

Task t = Task.Factory.StartNew(() => 
    { 
     /* Do Something */ 
    }, token).ContinueWith(ant => 
     { 
      /* Do something on UI thread after task has completed and check exceptions */ 
     }, CancellationToken.None, 
      TaskContinuationOptions.None, 
      scheduler); 

È anche possibile implementare manualmente il modello di TAP per un migliore controllo dell'attuazione. Per implementare personalmente il TAP, creare un oggetto TaskCompletionSource<TResult>, eseguire l'operazione asincrona e al termine, chiamare il metodo SetResult, SetException o SetCanceled o la versione Try di uno di questi metodi. Quando si implementa manualmente un metodo TAP, è necessario completare l'attività risultante al termine dell'operazione asincrona rappresentata. Per esempio:

public static Task<int> ReadTask(this Stream stream, 
    byte[] buffer, int offset, int count, object state) 
{ 
    var tcs = new TaskCompletionSource<int>(); 
    stream.BeginRead(buffer, offset, count, ar => 
    { 
     try { tcs.SetResult(stream.EndRead(ar)); } 
     catch (Exception exc) { tcs.SetException(exc); } 
    }, state); 
    return tcs.Task; 
} 

Consumare il TaskCompleationSource da parte del consumatore.

Spero che questo aiuti.

0

sì che ci sia.I wrapper asincroni per i metodi "Begin/End" mi vengono in mente;

public static Task<WebResponse> GetResponseAsync(this WebRequest client) 
{ 
return Task<WebResponse>.Factory.FromAsync(client.BeginGetResponse, 
client.EndGetResponse, null); 
} 

Credo che quello che state cercando Implement a WCF Asynchronous Service Operation with Task

+0

Grazie mille per aver condiviso bell'articolo @serbasi –

4

C'è un modo per utilizzare Task-based del modello asincrono (TAP) in .NET 4.0 senza la parola attendono o asincrono? Lo chiedo perché siamo bloccati in C# 4)

Un mod notevole e pratico è quello di utilizzare yield e IEnumerable<Task>. Per esempio, dal di "Processing Sequences of Asynchronous Operations with Tasks" Stephen Toub:

IEnumerable<Task> DoExample(string input) 
{ 
    var aResult = DoAAsync(input); 
    yield return aResult; 
    var bResult = DoBAsync(aResult.Result); 
    yield return bResult; 
    var cResult = DoCAsync(bResult.Result); 
    yield return cResult; 
    … 
} 

… 
Task t = Iterate(DoExample(“42”)); 

In questo modo, è possibile avere un flusso di codice lineare pseudo-sincrona simile a async/await.

+2

Questo è un ottimo modo di fare le cose che non richiede molto più di una partenza dal asincrona/modo 'await' di pensare (leggermente diversa gestione delle eccezioni a parte - non si può usa 'yield' nel corpo di un blocco' try-catch'). Non c'è niente di sbagliato con continuazioni e catene di continuazione in scenari semplici, ma quando si ha bisogno composizione ricca compito asincrona e non è possibile utilizzare 'async/await' questo è sicuramente la strada da percorrere. +1 –