Асинхронная и параллельная загрузка файлов

РЕДАКТИРОВАТЬ

Я изменил название вопроса, чтобы отразить возникшую у меня проблему, а также ответить на вопрос, как этого легко добиться.

Я пытаюсь сделать 2-й способ вернутьTask<TResult> вместоTask как в первом методе, но я получаю каскад ошибок как следствие попытки исправить это.

я добавилreturn доawait body(partition.Current);В свою очередь, он просит меня добавить оператор возврата ниже, поэтому я добавилreturn null нижеНо теперь оператор select жалуется, что не может вывести аргумент типа из запросая меняюTask.Run вTask.Run<TResult> но без успеха.

Как я могу это исправить?

Первый метод исходит отhttp://blogs.msdn.com/b/pfxteam/archive/2012/03/05/10278165.aspxВторой метод - это перегрузка, которую я пытаюсь создать.

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

Пример использования:

С помощью этого метода я хотел бы загружать несколько файлов параллельно и асинхронно:

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

Ответы на вопрос(1)

Ваш ответ на вопрос