Ich habe mehrere Dateien (fast je 1 GB) mit Daten. Daten sind eine Zeichenfolgelinie.
Ich muss jede dieser Dateien mit mehreren hundert Konsumenten verarbeiten. Jeder dieser Verbraucher führt eine Verarbeitung durch, die sich von anderen unterscheidet. Verbraucher schreiben nirgendwo gleichzeitig. Sie benötigen nur eine Eingabezeichenfolge. Nach der Verarbeitung aktualisieren sie ihre lokalen Puffer. Verbraucher können leicht parallel ausgeführt werden.
Wichtig: Mit einer bestimmten Datei muss jeder Verbraucher alle Zeilen (ohne zu überspringen) in der richtigen Reihenfolge (wie sie in der Datei erscheinen) verarbeiten. Die Reihenfolge der Verarbeitung verschiedener Dateien spielt keine Rolle.
Die Verarbeitung einer einzelnen Zeile durch einen Verbraucher ist vergleichsweise schnell. Ich erwarte weniger als 50 Mikrosekunden auf Corei5.
So, jetzt suche ich nach dem guten Ansatz für dieses Problem. Dies wird Teil eines .NET-Projekts sein, also bleiben wir lieber bei .NET (C # ist vorzuziehen).
Ich kenne TPL und DataFlow. Ich denke, dass die relevanteste wäre BroadcastBlock
. Aber ich denke, dass das Problem hier ist, dass ich mit jeder Linie warten muss, bis alle Verbraucher fertig sind, um die neue zu veröffentlichen. Ich denke, das wäre nicht sehr effizient.
Ich denke, dass die ideale Situation in etwa so aussehen würde:
Bin ich mit dieser Art von Ansatz richtig? Ob Ja oder Nein, wie kann ich die gute Lösung umsetzen?
Ich stimme nicht mit einem Thread liest aus den Dateien und schreibt in den Puffer
Bei mehreren Dateien von 1 GB würde dieser Thread zu viel Speicher verbrauchen
.NET hat eine Objektgrößenbeschränkung und eine Auflistung ist ein Objekt
Sie müssen die Leselinien drosseln Ich denke du könntest das mit einer BlockingCollection machen Die 1000000 der bc beschäftigt sich damit, den langsamsten Verbraucher beschäftigt zu halten Und es gibt auch einen Puffer für das Öffnen der nächsten Datei
%Vor%Ich habe kürzlich ein ähnliches Problem gelöst. Aber meine Lösung war nicht in C #, es war in SQL aufgrund der hohen Haltbarkeit Anforderungen, die ich hatte. Aber vielleicht helfen dir einige meiner Gedanken (so würde ich es machen):
Ich habe das "Unit of Work" -Paradigma verwendet. In Ihrem Fall können Sie eine Arbeitseinheit auswählen, z. 100-1000 Zeilen Text. In Ihrem Fall kann jede Arbeitseinheit durch Dateinamen, Startdateiposition und Enddateiposition gekennzeichnet sein. Jede Einheit weist auch eine Markierung auf, die angibt, ob sie von einem bestimmten Verbraucher verarbeitet wurde. Meine Arbeitseinheiten wurden als DB-Datensätze gespeichert; Sie können sie als Objekte in einer einfachen Speicherstruktur wie einer Liste speichern.
Nach dem Start Ihrer Anwendung wird ein separater Thread gestartet, der alle Dateien der Reihe nach liest und der Liste Arbeitseinheiten hinzufügt. Dieser Thread enthält eine Liste von zu verarbeitenden Dateien, liest sequentiell eine bestimmte Anzahl von Zeilen, speichert Dateipositionen und speichert Dateinamen und Dateipositionen in der Liste.
Solange einige Arbeitseinheiten in der Liste zur Verarbeitung verfügbar sind, beginnen die Verbraucher mit der Verarbeitung der Einheiten, die am Anfang der Liste beginnen. Um bestimmte Textzeilen für eine bestimmte Einheit zu erhalten, verwenden die Konsumenten ein Cache-Objekt. Solange alle Verbraucher mit der Verarbeitung am Anfang der Liste beginnen, besteht die große Chance, dass alle Verbraucher mindestens zu Beginn die gleiche zwischengespeicherte Arbeitseinheit anfordern.
Das Cache-Objekt ist absolut unabhängig von dem Thread, der der Liste Arbeitseinheiten hinzufügt. Die genaue Implementierung dieses Objekts hängt von einigen zusätzlichen Anforderungen ab, z. B. was tun, wenn einer der Benutzer abstürzt oder hängt, oder was zu tun ist, wenn die Anwendung neu gestartet wird, oder stimmen Sie zu, dass "schnelle" Verbraucher auf "langsame" Verbraucher warten. wie möchten Sie den gesamten Prozess überwachen, etc ...
Hoffe, das hilft ...
Tags und Links .net c# multithreading task-parallel-library tpl-dataflow