Ich versuche, eine asynchrone Konsolen-App zu erstellen, die einige Arbeiten an einer Sammlung ausführt. Ich habe eine Version, die parallel for loop verwendet, eine andere Version, die async / await verwendet. Ich habe erwartet, dass die asynchrone / warte-Version ähnlich wie die parallele Version funktioniert, aber sie wird synchron ausgeführt. Was mache ich falsch?
class Program
{
static void Main(string[] args)
{
var worker = new Worker();
worker.ParallelInit();
var t = worker.Init();
t.Wait();
Console.ReadKey();
}
}
public class Worker
{
public async Task<bool> Init()
{
var series = Enumerable.Range(1, 5).ToList();
foreach (var i in series)
{
Console.WriteLine("Starting Process {0}", i);
var result = await DoWorkAsync(i);
if (result)
{
Console.WriteLine("Ending Process {0}", i);
}
}
return true;
}
public async Task<bool> DoWorkAsync(int i)
{
Console.WriteLine("working..{0}", i);
await Task.Delay(1000);
return true;
}
public bool ParallelInit()
{
var series = Enumerable.Range(1, 5).ToList();
Parallel.ForEach(series, i =>
{
Console.WriteLine("Starting Process {0}", i);
DoWorkAsync(i);
Console.WriteLine("Ending Process {0}", i);
});
return true;
}
}
c#
.net
async-await
Satish
quelle
quelle
Ending Process
Benachrichtigung nicht angezeigt wird, wenn die Aufgabe tatsächlich beendet wird. Alle diese Benachrichtigungen werden direkt nach Abschluss der letzten Aufgabe nacheinander ausgegeben. Zu dem Zeitpunkt, an dem "Prozess 1 beenden" angezeigt wird, ist Prozess 1 möglicherweise schon lange beendet. Abgesehen von der Wortwahl dort +1.Semaphore
InDoWorkAsync
zu implementieren , um die maximal ausgeführten Aufgaben zu begrenzen?Ihr Code wartet, bis jede Operation (mit
await
) abgeschlossen ist, bevor die nächste Iteration gestartet wird.Daher erhalten Sie keine Parallelität.
Wenn Sie eine vorhandene asynchrone Operation parallel ausführen möchten, benötigen Sie keine
await
; Sie müssen nur eine Sammlung vonTask
s abrufen und aufrufenTask.WhenAll()
, um eine Aufgabe zurückzugeben, die auf alle wartet:quelle
await
genau das Gegenteil von dem, was Sie wollen - es wartet darauf, dass dasTask
Ende ist.DoWorkAsync
für jedes Element aufgerufene Aufgabe ausgeführtlist
(Übergabe jedes Elements anDoWorkAsync
, von dem ich annehme, dass es einen einzelnen Parameter hat)?quelle
In C # 7.0 können Sie jedem Mitglied des Tupels semantische Namen geben. Hier ist die Antwort von Tim S. mit der neuen Syntax:
Sie könnten auch
task.
innenforeach
loswerden :quelle