Willkommen auf myCSharp.de! Anmelden | kostenlos registrieren
 | Suche | FAQ

Hauptmenü
myCSharp.de
» Startseite
» Forum
» Suche
» Regeln
» Wie poste ich richtig?

Mitglieder
» Liste / Suche
» Wer ist online?

Ressourcen
» FAQ
» Artikel
» C#-Snippets
» Jobbörse
» Microsoft Docs

Team
» Kontakt
» Cookies
» Spenden
» Datenschutz
» Impressum

  • »
  • Community
  • |
  • Diskussionsforum
Wie kann ich Requests am besten parallel abarbeiten?
Sarevok
myCSharp.de - Member



Dabei seit:
Beiträge: 2

Themenstarter:

Wie kann ich Requests am besten parallel abarbeiten?

beantworten | zitieren | melden

Liebe Gemeinde-

Ich mache grade meine ersten Schritte mit C# und .NET, genauer gesagt ganz simple Konsolenanwendungen in .NET Core und Visual Studio Code.

Ich habe nun eine Anwendung welche aus einer externen Quelle Daten bekommt, diese eine Weile lang aufbereitet und schließlich auf einem Webserver speichert.

Mittlerweile gehe ich noch ganz stumpf seriell vor:
  1. Daten einholen
  2. Daten aufbereiten
  3. Daten versenden


  4. Klar: Schritt 1,2 & 3 ließen sich optimieren indem dort parallel gearbeitet würde - Die Möglichkeiten in C# mit System.Threading.Tasks.Parallel sind so enorm wie komfortabel - Das bekomme ich noch hin.


    Mir geht es darum dass ich nach dem Einholen (1) der ersten Daten eigentlich schon diese aufbereiten (2) könnte. Und wenn aufbereitet, schon versenden (3). Das, während noch Daten weiter abgeholt werden (1), denn es sind einige.

    Meine Frage: Wie macht man das in C# typischerweise? Ich tue mich schwer hier etwas zu finden. Klar könnte man einfach Dinge in eine Warteschlange für jeweils Schritt 1, 2, 3 packen und jeweils ein Thread kümmert sich um die Dinge aus der für ihn gedachten Warteschlage.

    Aber ich würde erwarten dass es hier in der Standard-Bibliothek etwas gibt, dieses "Pipelining" wäre ja kein so unübliches Konzept. Kann mir hier jemand aushelfen? Ich fand bislang nur ein komisches DataFlow-Ding, aber das scheint noch nicht einmal Bestandteil der Standard .NET Bibliothek zu sein...
private Nachricht | Beiträge des Benutzers
T-Virus
myCSharp.de - Member



Dabei seit:
Beiträge: 1768
Herkunft: Nordhausen, Nörten-Hardenberg

beantworten | zitieren | melden

Da die Prozesse am Fließband abgearbeitet werden müssen, kannst du pro Durchlauf für alle drei Abläufe einen Thread verwenden.
Entsprechend macht es Sinn alle drei Abläufe durch einen Task verarbeiten zu lassen.
Somit kannst du pro Durchlauf einen eigenen Task erstellen lassen, der dann eben alle drei Prozesse durchläuft.

Nachtrag:
Da du nicht auf alle Daten in Schritt 1 warten musst , kannst du hier z.B. mit yield return bei 1 dann jeweils den aktuellen Datensatz liefern.
Somit kannst du in einer einfachen foreach Schleife solange Daten lesen und an 2 weiterleiten, bis es keine Daten mehr gibt.
Dann kannst du von 2 das Ergebnis abwarten per async/await um es dann wieder bei 3 an den Webserver zu senden.

T-Virus
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von T-Virus am .
Developer, Developer, Developer, Developer....

99 little bugs in the code, 99 little bugs. Take one down, patch it around, 117 little bugs in the code.
private Nachricht | Beiträge des Benutzers
Sarevok
myCSharp.de - Member



Dabei seit:
Beiträge: 2

Themenstarter:

beantworten | zitieren | melden

Stimmt, Schritt 1, 2 und 3 folgen ja zwingend aufeinander. Das ist ein guter Punkt.

Auch dieses komische yield-Gedöns hatte ich schon nicht mehr auf dem Schirm, daran muss man sich erst einmal gewöhnen. Vielen Dank für den Tipp
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von Sarevok am .
private Nachricht | Beiträge des Benutzers
Abt
myCSharp.de - Team

Avatar #avatar-4119.png


Dabei seit:
Beiträge: 15536
Herkunft: BW

beantworten | zitieren | melden

Zitat von T-Virus
Da die Prozesse am Fließband abgearbeitet werden müssen, kannst du pro Durchlauf für alle drei Abläufe einen Thread verwenden.
Entsprechend macht es Sinn alle drei Abläufe durch einen Task verarbeiten zu lassen.
Somit kannst du pro Durchlauf einen eigenen Task erstellen lassen, der dann eben alle drei Prozesse durchläuft.
ganz klares, dickes, deutliches Nein; das macht kein Sinn!
Das passt nicht, denn das würde auch nicht skalieren - außer Sarevok will gar keine skalierende Lösung. ;-)

Das widerspricht auch dem Sinn von Datenfluss.
Die Idee von Datenfluss ist auch, dass unterschiedliche Aufgaben, die unterschiedliche Ressourcen (IO vs CPU vs RAM) und Zeit benötigen auch unterschiedlich skaliert werden.
Das geht natürlich nicht, wenn alles in einem Ausführungsrahmen (Thread oder Task) erfolgt.

Und genau das hier haben wir hier offensichtlich: I/O und CPU-bound tasks.
Das unter einen Hut zu packen: absolut not best practise!
Seit Jahren betreibt Microsoft große Anstrengungen mit Dokumentation, Bibliotheken und Co, dass die Leute eben nicht mehr alles in einen Task packen!
Siehe auch die Archiv-Dokumentation aus 2012 des DataFlow-Vorgängers: Pipelines Basics inkl. entsprechender Grafiken.

Daher widerspreche ich auch
Zitat von T-Virus
Entsprechend macht es Sinn alle drei Abläufe durch einen Task verarbeiten zu lassen.
in vollem Umfang.

Aber DataFlow ist der korrekte Ansatz hier.
Zitat von Sarevok
Ich fand bislang nur ein komisches DataFlow-Ding, aber das scheint noch nicht einmal Bestandteil der Standard .NET Bibliothek zu sein...

System.Threading.Tasks.Dataflow

PS: .NET Standard ist keine Bibliothek, sondern als Interface zu sehen. .NET Core bzw. .NET Framework ist dann eine Implementierung dessen.
Der Standard deckt die Funktionalitäten eines gemeinsamen Grundstandards ab, auf dem dann Bibliotheken wie DataFlow basieren bzw. entwickelt werden können.
Es ist aber nicht notwendig oder gedacht, dass Dinge wie DataFlow Teil des Standards sind - macht kein Sinn.
PPS: yield ist kein Skalierungswerkzeug. ;-)
private Nachricht | Beiträge des Benutzers
gfoidl
myCSharp.de - Team

Avatar #avatar-2894.jpg


Dabei seit:
Beiträge: 7510
Herkunft: Waidring

beantworten | zitieren | melden

Hallo T-Virus,
Zitat
Entsprechend macht es Sinn alle drei Abläufe durch einen Task verarbeiten zu lassen.
du hast sicher "je einen Task" gemeint?
Wenn das dann korrekt umgesetzt wird, so sind wir bei Abts Antwort.

mfG Gü
Stellt fachliche Fragen bitte im Forum, damit von den Antworten alle profitieren. Daher beantworte ich solche Fragen nicht per PM.

"Alle sagten, das geht nicht! Dann kam einer, der wusste das nicht - und hat's gemacht!"
private Nachricht | Beiträge des Benutzers
Abt
myCSharp.de - Team

Avatar #avatar-4119.png


Dabei seit:
Beiträge: 15536
Herkunft: BW

beantworten | zitieren | melden

Zitat von gfoidl
du hast sicher "je einen Task" gemeint?

Entsprechend
Zitat von T-Virus
Somit kannst du pro Durchlauf einen eigenen Task erstellen lassen, der dann eben alle drei Prozesse durchläuft.

1 Durchlauf = alle drei Prozesse = einen Task

wird er nicht "je einen Task" gemeint haben, sonst würde der Satzzusammenhang insich nicht stimmen.
Dahingehend basierend meine ausführliche, korrigierende Antwort.
private Nachricht | Beiträge des Benutzers
T-Virus
myCSharp.de - Member



Dabei seit:
Beiträge: 1768
Herkunft: Nordhausen, Nörten-Hardenberg

beantworten | zitieren | melden

@Abt
Hast du meinen Nachtrag bei deinen Antworten ignoriert?
Dieser sagt ja, dass er nicht alles in einem Thread/Task machen muss sondern jeweils nach und nach diese durch eigene Tasks abarbeiten kann.
Ich hatte beim ersten durchlesen überlesen, dass er eben nicht auf alle Daten aus Schritt 1 warten muss sondern diese quasi Stück für Stück abarbeiten kann.

Mit DataFlows habe ich leider keine Erfahrungen, weshalb ich dies erst einmal außer acht gelassen habe.
Wenn dies der korrekte Ansatz ist, dann sind meine Antworten eh hinfällig.

T-Virus
Developer, Developer, Developer, Developer....

99 little bugs in the code, 99 little bugs. Take one down, patch it around, 117 little bugs in the code.
private Nachricht | Beiträge des Benutzers
Abt
myCSharp.de - Team

Avatar #avatar-4119.png


Dabei seit:
Beiträge: 15536
Herkunft: BW

beantworten | zitieren | melden

Dein Nachtrag ändert weder am ersten Teil noch an der Sache was; daher ja auch mein Hinweis, dass yield schön und gut ist, aber das halt trotzdem kein Skalierungswerkzeug ist ;-)
Und wie geschrieben: auch vor dem Datenfluss war es noch nie eine gute Idee alles in einen Task zu packen (siehe Link aus 2012).
private Nachricht | Beiträge des Benutzers
ThomasE.
myCSharp.de - Member



Dabei seit:
Beiträge: 453

beantworten | zitieren | melden

Hallo,

ich möchte mich für die Verlinkung DataFlow bedanken, das ist nämlich genau das, was ich auch benötige!

Hab mir das angesehen und es ist wirklich ein tolle Sache! Vereinfacht die Arbeit ungemein!

Danke!
Ich habe den Titel mal angepasst, so dass Suchende auch etwas damit anfangen können. EDIT: Ich sollte beim Wort "Shift" im Titel das "f" nicht vergessen...
private Nachricht | Beiträge des Benutzers