Download de forma assíncrona e paralela de arquivos

EDITAR

Eu mudei o título da pergunta para refletir o problema que eu tinha, mas também uma resposta sobre como conseguir isso facilmente.

Eu estou tentando fazer o segundo método para retornarTask<TResult> ao invés deTask como no primeiro método, mas estou recebendo uma cascata de erros como consequência de tentar corrigi-lo.

Eu adicioneireturn antesawait body(partition.Current);Por sua vez, pede-me para adicionar uma declaração de retorno abaixo, então eu adicioneireturn null abaixoMas agora a instrução select reclama que não pode inferir o argumento type da consultaeu mudoTask.Run paraTask.Run<TResult> mas sem sucesso.

Como posso consertar isso?

O primeiro método vem dehttp://blogs.msdn.com/b/pfxteam/archive/2012/03/05/10278165.aspx, o segundo método é a sobrecarga que estou tentando criar.

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

Exemplo de uso:

Com esse método, eu gostaria de baixar vários arquivos em paralelo e de forma assíncrona:

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