Ich habe gesehen, dass Parallel.ForEach unangemessen verwendet wurde, und ich dachte, ein Beispiel in dieser Frage würde helfen.
Wenn Sie den folgenden Code in einer Konsolen-App ausführen, sehen Sie, wie die in Parallel.ForEach ausgeführten Aufgaben den aufrufenden Thread nicht blockieren. Dies kann in Ordnung sein, wenn Sie sich nicht für das Ergebnis interessieren (positiv oder negativ), aber wenn Sie das Ergebnis benötigen, sollten Sie sicherstellen, dass Sie Task.WhenAll verwenden.
using System;
using System.Linq;
using System.Threading.Tasks;
namespace ParrellelEachExample
{
class Program
{
static void Main(string[] args)
{
var indexes = new int[] { 1, 2, 3 };
RunExample((prefix) => Parallel.ForEach(indexes, (i) => DoSomethingAsync(i, prefix)),
"Parallel.Foreach");
Console.ForegroundColor = ConsoleColor.Yellow;
Console.WriteLine("*You'll notice the tasks haven't run yet, because the main thread was not blocked*");
Console.WriteLine("Press any key to start the next example...");
Console.ReadKey();
RunExample((prefix) => Task.WhenAll(indexes.Select(i => DoSomethingAsync(i, prefix)).ToArray()).Wait(),
"Task.WhenAll");
Console.WriteLine("All tasks are done. Press any key to close...");
Console.ReadKey();
}
static void RunExample(Action<string> action, string prefix)
{
Console.ForegroundColor = ConsoleColor.White;
Console.WriteLine($"{Environment.NewLine}Starting '{prefix}'...");
action(prefix);
Console.WriteLine($"{Environment.NewLine}Finished '{prefix}'{Environment.NewLine}");
}
static async Task DoSomethingAsync(int i, string prefix)
{
await Task.Delay(i * 1000);
Console.WriteLine($"Finished: {prefix}[{i}]");
}
}
}
Hier ist das Ergebnis:
Fazit:
Wenn Sie Parallel.ForEach mit einer Aufgabe verwenden, wird der aufrufende Thread nicht blockiert. Wenn Sie sich für das Ergebnis interessieren, warten Sie auf die Aufgaben.
~ Prost
Task.WaitAll
stattdessen verwenden würdenTask.WhenAll
.