EDITAsynchron und parallel das Herunterladen von Dateien
Ich habe den Titel der Frage geändert, um die Frage zu reflektieren Ich hatte aber auch eine Antwort, wie dies leicht zu erreichen.
Ich versuche, die zweite Methode, um es zurück Task<TResult>
statt Task
wie in der 1. Methode, aber ich erhalte eine Kaskade von Fehlern als Folge zu beheben versuchen.
- Ich habe
return
vorawait body(partition.Current);
- wiederum aufgefordert, mich mich unter so hinzugefügt, um eine return-Anweisung hinzufügen
return null
unter - Aber jetzt ist die select-Anweisung beklagt, dass sie die Art Argument aus der Abfrage nicht ableiten können
- Ich ändere
Task.Run
zuTask.Run<TResult>
aber ohne Erfolg.
Wie kann ich es beheben? Die erste Methode kommt von http://blogs.msdn.com/b/pfxteam/archive/2012/03/05/10278165.aspx, die zweite Methode ist die Überladung, die ich versuche zu erstellen.
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 würde Ich mag mehrere Dateien parallel und asynchron zum Download:
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;
}
}
Es ist nicht klar, was man erwarten würde. Du gibst eine ganze Folge von 'T'-Werten ein und führst die gleiche Funktion auf beiden aus - welches einzige Ergebnis würdest du erwarten, um aus der' Task 'zurück zu kommen? –
Ich möchte eine Aufgabe bekommen in diesem Fall habe ich ein Beispiel zu meiner Frage hinzugefügt. –
Aybe
* "Mit dieser Methode möchte ich mehrere Dateien parallel und asynchron herunterladen" *: 'Parallel.Foreach' ist nicht genug? –