2012-11-14 21 views
10

Quale sarebbe l'alternativa migliore per la parola chiave await in .NET 4.0? Ho un metodo che deve restituire un valore dopo un'operazione asincrona. Ho notato che il metodo wait() blocca completamente il thread, rendendo così inutile l'operazione asincrona. Quali sono le opzioni per eseguire l'operazione asincrona mentre si sta ancora liberando il thread dell'interfaccia utente?Attendi un'alternativa in .NET 4.0?

+1

uso attendo, ma nel modo giusto credo. Hai del codice? – lboshuizen

+3

È accettabile utilizzare VS2012 con C# 5.0 durante il targeting .net 4.0? Vedi [Uso di async-await su .net 4] (http://stackoverflow.com/questions/9110472/using-async-await-on-net-4) – CodesInChaos

+0

@CodesInChaos Per i colleghi, no :). – Dante

risposta

4

penso che le opzioni di base sono

Il modo più semplice è probabilmente quello di installare il CTP asincrono. Per quanto ne so, la licenza consente l'uso commerciale. Aggiusta il compilatore e viene fornito con una dll da 150kb che puoi includere nel tuo progetto.

È possibile utilizzare Task e .ContinueWith(). Ma questo significa che devi fare qualche sforzo con la gestione dell'eccezione e il controllo del flusso.

Le attività sono un costrutto funzionale. Ecco perché lo ContinueWith() non si combina bene con i costrutti imperativi come i loop for o i blocchi try-catch. Pertanto sono stati introdotti async e await, in modo che il compilatore possa aiutarci.

Se non si dispone del supporto del compilatore (ad esempio, si utilizza .Net 4.0), la soluzione migliore è utilizzare lo TAP insieme a un framework funzionale. Reactive Extensions è un ottimo framework per il trattamento di metodi asincroni.

Basta google per "attività di estensioni reattive" per iniziare.

1

È possibile implementare un comportamento come await con le coroutine di yield, sto usando questo codice non 4.5. Avete bisogno di una classe YieldInstruction che viene recuperato dal metodo che dovrebbe essere eseguito asincrona:

public abstract class YieldInstruction 
{ 
    public abstract Boolean IsFinished(); 
} 

allora avete bisogno di alcune implementazioni del YieldInstruction (ae TaskCoroutine che gestisce un compito) e usarlo in questo modo (Pseudo codice):

public IEnumerator<YieldInstruction> DoAsync() 
{ 
    HttpClient client = ....; 
    String result; 
    yield return new TaskCoroutine(() => { result = client.DownloadAsync(); }); 
    // Process result here 
} 

Ora è necessario uno scheduler che gestisca l'esecuzione delle istruzioni.

for (Coroutine item in coroutines) 
{ 
    if (item.CurrentInstruction.IsFinished()) 
    { 
     // Move to the next instruction and check if coroutine has been finished 
     if (item.MoveNext()) Remove(item); 
    } 
} 

Quando si sviluppano applicazioni WPF o WinForms si sono anche in grado di evitare qualsiasi Invoke chiamate se si sta aggiornando i coroutine al momento giusto. Potresti anche essere in grado di estendere l'idea per rendere la tua vita ancora più facile. Esempio:

public IEnumerator<YieldInstruction> DoAsync() 
{ 
    HttpClient client = ....; 
    client.DownloadAsync(..); 

    String result; 
    while (client.IsDownloading) 
    { 
     // Update the progress bar 
     progressBar.Value = client.Progress; 
     // Wait one update 
     yield return YieldInstruction.WaitOneUpdate; 
    } 
    // Process result here 
}