Asynchroniczne i równoległe pobieranie plików

EDYTOWAĆ

Zmieniłem tytuł pytania, aby odzwierciedlić problem, który miałem, ale także odpowiedź na pytanie, jak łatwo to osiągnąć.

Próbuję powrócić do drugiej metodyTask<TResult> zamiastTask jak w pierwszej metodzie, ale otrzymuję kaskadę błędów jako konsekwencję próby naprawy.

dodałemreturn przedawait body(partition.Current);Z kolei prosi mnie o dodanie poniższego oświadczenia zwrotnego, więc dodałemreturn null poniżejAle teraz instrukcja select skarży się, że nie może wywnioskować argumentu typu z zapytaniazmieniamTask.Run doTask.Run<TResult> ale bez powodzenia.

Jak mogę to naprawić?

Pierwsza metoda pochodzi odhttp://blogs.msdn.com/b/pfxteam/archive/2012/03/05/10278165.aspx, druga metoda to przeciążenie, które próbuję stworzyć.

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);
            }));
    }
}

Przykład użycia:

Dzięki tej metodzie chciałbym pobrać wiele plików równolegle i asynchronicznie:

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;
    }
}

questionAnswers(1)

yourAnswerToTheQuestion