2010-09-14 13 views
5

Derzeit habe ich einen Abschnitt Code, der etwa 7 Web Service-Aufrufe an verschiedene Anbieter für Daten vornehmen muss. Jeder Aufruf dauert einige Sekunden, also möchte ich sie parallel ausführen, um die Dinge zu beschleunigen.Verwenden von .Net Parallel Extensions (Parallel.Invoke) für mehrere asynchrone Aufrufe?

Ich habe meine 7 Anrufe in eine Parallel.Invoke eingewickelt, die gut funktioniert, ein paar Dinge gleichzeitig zu laufen, aber auf einem 2-Core-Server wird es nur 2 zu einer Zeit ausführen, eine pro Kern. Da alles, was ich tue, wartet auf die Web-Service-Anrufe, um zurückzukehren, würde ich wollen, dass es alle 7 holen und warten auf sie zurückkommen.

Gibt es keine Möglichkeit, dies zu tun? Oder ist mein Ansatz falsch? Vielleicht muss ich asynchrone Aufrufe an die Webdienste erstellen? Aber wie kann man dann darauf warten, dass alle wiederkommen, bevor sie weiterziehen?

Antwort

5

aber auf einem 2-Kern-Server, wird es nur 2 zu einem Zeitpunkt

, einen pro Kern ausführen

Ich würde diese Frage - Parallel.Invoke wird in der Regel viel mehr Aufgaben als Kern in Ihrem System ausgeführt werden .

Das heißt, wenn Sie Aufrufaufrufe mit asynchronen Methoden verwenden, würde ich empfehlen, Task.Factory.FromAsync(...) zu verwenden, um Ihre sieben verschiedenen Aufgaben zu generieren.

Dies bietet die Flexibilität, andere Aufgaben auszuführen, während die Aufgaben ausgeführt werden, und ruft dann Task.WaitAll (oder Task.WaitAny) auf, wenn Sie sich für die Verwendung der Ergebnisse entscheiden.

Parallel.Invoke dagegen wird immer blockieren, bis alle sieben abgeschlossen sind.

+2

Ich hatte den Eindruck, dass er wollte, dass alle fertig waren, bevor er fortfuhr. –

+1

@Steven: Was kann er über Task.WaitAll tun - aber er kann andere Arbeit erledigen, während er wartet, wenn es verfügbar ist, wenn das eine Option ist. Fälle wie diese arbeiten jedoch oft mit Task.WaitAny, da Sie normalerweise einen Teil der Arbeit starten können, sobald einige der Aufgaben abgeschlossen sind - es ist selten, dass Sie 7 verschiedene Ergebnisse benötigen, um eine Verarbeitung durchzuführen ... –

+0

Sie sind richtig, das wird auch funktionieren und flexibler als das, was ich vorgeschlagen habe. –

0

Sie können ParallelOptions angeben, um die Parallelität zu erhöhen. Der Standardwert ist für CPU-gebundene Tasks geeignet, Sie haben es jedoch mit I/O-gebundenen Tasks zu tun, daher ist es sinnvoll, dieses Verhalten zu überschreiben.

+0

Ich dachte, die Erhöhung des Gleichzeitigkeitsniveaus geht nur so weit wie die maximale Parallelität erlaubt? dh wenn Sie 8 Kerne haben, können Sie den Nebenläufigkeitslevel auf alles einstellen..aber höher als 8 geht nichts ... – puffpio

+0

@puffpio: Alles, was es sagt, ist: "MaxDegreeOfParallelism begrenzt die Anzahl der gleichzeitigen Operationen, die von parallelen Methodenaufrufen ausgeführt werden, die diese ParallelOptions-Instanz an den gesetzten Wert übergeben, wenn es positiv ist. Wenn MaxDegreeOfParallelism -1 ist, gibt es keine Begrenzung auf die Anzahl der gleichzeitig ausgeführten Operationen gesetzt. " –

+0

Ja, das verwirrt mich, da es "Limit" bedeutet, was für mich bedeutet, dass es nicht über die Anzahl der Kerne hinausgeht, die du hast. Ich sage das, weil die Seite auf Parallel.Invoke sagt: "Beachten Sie, dass Sie mit Invoke() einfach angeben, welche Aktionen gleichzeitig ausgeführt werden sollen, und die Laufzeit alle Thread-Planungsdetails behandelt, einschließlich der automatischen Skalierung auf die Anzahl der Kerne Host-Computer." – puffpio

1

Es gibt keine echte Notwendigkeit, Parallel.Invoke dafür zu verwenden. Sie können fortfahren und die mehreren asynchronen Anforderungen ausgeben (d. H. HttpWebRequest.BeginGetResponse()). Wenn Sie benachrichtigt werden, wenn alle fertig sind, haben Sie mehrere Möglichkeiten. Ein einfacher Weg wäre, eine CountdownEvent zu initialisieren, bevor Sie die erste Anfrage ausgeben, und dann den Hauptthread auf dieses Ereignis warten lassen, nachdem es die Anfragen ausgegeben hat. Die asynchronen Rückrufmethoden signalisieren jeweils das Ereignis, wenn sie abgeschlossen sind. Auf diese Weise stellen Sie sicher, dass alle Anforderungen abgeschlossen sind, bevor der Hauptthread fortgesetzt wird.

+1

Aber TPL ist so viel _easier_ als das APM. Es wäre schön, wenn wir das Beste aus beiden Welten hätten. –

+0

Die Verwendung von Task.Factory.StartAsync bietet das Beste aus beiden Welten ... ohne die Notwendigkeit, mit CountdownEvent usw. zu verfolgen. –

+0

Ich muss die TPL genauer betrachten. –

0

Ich werde a response that I made to another question wörtlich kopieren, weil es in gleicher Weise, wenn nicht mehr, hier anwendbar ist.


Sie können das asynchrone Programmiermodell (APM) einfach nicht schlagen, wenn es um I/O-Leistung geht. Immer wenn du es benutzen kannst, solltest du es sein. Glücklicherweise bietet die Task Parallel Library (TPL) Unterstützung für die Kombination von APM-Arbeit in den Mix mit "reinen" TPL-Aufgaben über the FromAsync factory method.

In diesem Abschnitt des .NET SDK auf MSDN mit dem Titel TPL and Traditional .NET Asynchronous Programming finden Sie weitere Informationen zum Kombinieren dieser beiden Programmiermodelle, um asynchres Nirvana zu erzielen.

Verwandte Themen