Asynchrones und paralleles Herunterladen von Dateien

BEARBEITEN

Ich habe den Titel der Frage geändert, um das Problem wiederzugeben, das ich hatte, aber auch eine Antwort darauf, wie dies leicht zu erreichen ist.

Ich versuche, die 2. Methode zu machen, um zurückzukehrenTask<TResult> anstattTask Wie bei der ersten Methode, aber ich erhalte eine Kaskade von Fehlern als Folge des Versuchs, sie zu beheben.

Ich fügte hinzureturn Vorawait body(partition.Current);Im Gegenzug werde ich gebeten, unten eine return-Anweisung hinzuzufügen, damit ich sie hinzufügereturn null untenJetzt beklagt sich die select-Anweisung, dass das type-Argument nicht aus der Abfrage abgeleitet werden kannIch ändereTask.Run zuTask.Run<TResult> aber ohne Erfolg.

Wie kann ich es reparieren ?

Die erste Methode kommt vonhttp://blogs.msdn.com/b/pfxteam/archive/2012/03/05/10278165.aspxDie zweite Methode ist die Überladung, die ich zu erstellen versuche.

public static class Extensions
{
    public static Task ForEachAsync<T>(this IEnumerable<T> source, int dop, Func<T, Task> body)
    {
        return Task.WhenAll(
            from partition in Partitioner.Create(source).GetPartitions(dop)
            select Task.Run(async delegate
            {
                using (partition)
                    while (partition.MoveNext())
                        await body(partition.Current);
            }));
    }

    public static Task ForEachAsync<T, TResult>(this IEnumerable<T> source, int dop, Func<T, Task<TResult>> body)
    {
        return Task.WhenAll(
            from partition in Partitioner.Create(source).GetPartitions(dop)
            select Task.Run(async delegate
            {
                using (partition)
                    while (partition.MoveNext())
                        await body(partition.Current);
            }));
    }
}

Anwendungsbeispiel:

Mit dieser Methode möchte ich mehrere Dateien gleichzeitig und asynchron herunterladen:

private async void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
    Artist artist = await GetArtist();
    IEnumerable<string> enumerable = artist.Reviews.Select(s => s.ImageUrl);
    string[] downloadFile = await DownloadFiles(enumerable);
}

public static async Task<string[]> DownloadFiles(IEnumerable<string> enumerable)
{
    if (enumerable == null) throw new ArgumentNullException("enumerable");
    await enumerable.ForEachAsync(5, s => DownloadFile(s));
    // Incomplete, the above statement is void and can't be returned
}

public static async Task<string> DownloadFile(string address)
{
    /* Download a file from specified address, 
        * return destination file name on success or null on failure */

    if (address == null)
    {
        return null;
    }

    Uri result;
    if (!Uri.TryCreate(address, UriKind.Absolute, out result))
    {
        Debug.WriteLine(string.Format("Couldn't create URI from specified address: {0}", address));
        return null;
    }

    try
    {
        using (var client = new WebClient())
        {
            string fileName = Path.GetTempFileName();
            await client.DownloadFileTaskAsync(address, fileName);
            Debug.WriteLine(string.Format("Downloaded file saved to: {0} ({1})", fileName, address));
            return fileName;
        }
    }
    catch (WebException webException)
    {
        Debug.WriteLine(string.Format("Couldn't download file from specified address: {0}", webException.Message));
        return null;
    }
}

Antworten auf die Frage(1)

Ihre Antwort auf die Frage