Descarga asíncrona y paralela de archivos.

EDITAR

He cambiado el título de la pregunta para reflejar el problema que tenía, pero también una respuesta sobre cómo lograrlo fácilmente.

Estoy tratando de hacer el segundo método para volverTask<TResult> en lugar deTask como en el 1er método, pero recibo una cascada de errores como consecuencia de intentar solucionarlo.

yo añadíreturn antes deawait body(partition.Current);A su vez, me pide que agregue una declaración de devolución a continuación, así que agreguéreturn null abajoPero ahora la declaración de selección se queja de que no puede inferir el argumento de tipo de la consultaYo cambioTask.Run aTask.Run<TResult> pero sin éxito.

Cómo puedo arreglarlo ?

El primer método viene dehttp://blogs.msdn.com/b/pfxteam/archive/2012/03/05/10278165.aspx, el segundo método es la sobrecarga que estoy tratando de crear.

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

Ejemplo de uso:

Con este método me gustaría descargar varios archivos en paralelo y asincrónicamente:

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

Respuestas a la pregunta(1)

Su respuesta a la pregunta