2014-05-13 14 views
9

Ich versuche, meinen Kopf herum zu wickeln async/await und wollte wissen, ob dies die richtige Verwendung des Task.WhenAll Methode ist:Der richtige Einsatz von Task.WhenAll

public class AsyncLib 
{ 
    public async Task<IEnumerable<string>> DoIt() 
    { 
     var urls = new string[] { "http://www.msn.com", "http://www.google.com" }; 

     var tasks = urls.Select(x => this.GetUrlContents(x)); 

     var results = await Task.WhenAll(tasks); 

     return results.Select(x => x); 
    } 

    public async Task<string> GetUrlContents(string url) 
    { 
     using (var client = new WebClient()) 
     { 
      return await client.DownloadStringTaskAsync(url); 
     } 
    } 
} 

Haupt

Diese ist die Anrufkonsolenanwendung.

class Program 
{ 
    static void Main(string[] args) 
    { 
     var lib = new AsyncLib(); 
     foreach(var item in lib.DoIt().Result) 
     { 
      Console.WriteLine(item.Length); 
     } 
     Console.Read(); 

    } 
} 
+2

Definieren Sie "richtig" ..? –

+0

@SimonWithehead - Ich bin neu in Async/erwarten, also versuche nur, meinen Kopf darum herum zu wickeln. Korrekt würde ich sagen, "Gibt es einen besseren Weg?" – Sam

+1

Dies ist im Allgemeinen, wie ich es gesehen habe/gesehen habe. Sie müssen auf eine Reihe von Aufgaben warten, um asynchron abzuschließen. 'WhenAll 'ist im Allgemeinen wie Sie es tun (das ich weiß). –

Antwort

14

Das Problem mit Ihrem aktuellen Code ist, dass Sie einzelne Ausnahmen nicht behandeln können, wenn mehr als eine Aufgabe löst.

Wenn dies ein Problem ist, dann mit dem folgenden Ansatz, können Sie mit ihnen umgehen:

public async Task<Task<string>[]> DoIt() 
{ 
    var urls = new string[] { "http://www.msn.com", "http://www.google.com" }; 

    var tasks = urls.Select(x => this.GetUrlContents(x)).ToArray(); 

    await Task.WhenAll(tasks); 

    return tasks; 
} 

// ... 

static void Main(string[] args) 
{ 
    var lib = new AsyncLib(); 
    foreach(var item in lib.DoIt().Result) 
    { 
     Console.WriteLine(item.Result.Length); 
    } 
    Console.Read(); 

} 

Hinweis I ToArray() verwenden, um zu vermeiden, die zählbaren Bewertung und beginnt, die Aufgaben für mehr als einmal (wie LINQ faul -bewertet).

aktualisiert, jetzt weiter DoIt durch async/await Beseitigung optimieren können:

public Task<Task<string>[]> DoIt() 
{ 
    var urls = new string[] { "http://www.msn.com", "http://www.google.com" }; 

    var tasks = urls.Select(x => this.GetUrlContents(x)).ToArray(); 

    return Task.Factory.ContinueWhenAll(
     tasks, 
     _ => tasks, 
     CancellationToken.None, 
     TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default); 
} 

Allerdings, wenn Sie dies tun, beachten Sie die Änderung der exception propagation behavior.

+3

+1 für das Hinweisen auf faule Auswertung von Select. –

Verwandte Themen