Sunday 19 November 2017

Omnithreadlibrary Waitforexit


Die meiste Zeit der Arbeit als Entwickler gibt uns die Freiheit, in unserer hoch-Ebene der Abstraktion Welt herum, aber manchmal Realität tritt Sie in den privaten Teilen und sagt Ihnen, einen Mann, der wirklich versteht. Ive hatte nur eine dieser Erfahrungen. Ich denke, itll genügt, um die Eckdaten als eine Liste für Sie zu finden, um zu verstehen, was wir hier haben: Win2008 Server 64Bit Umgebung WPF Anwendung, die von mehreren Clients gleichzeitig Anwendung ist ein Launcher, die öffnet andere Anwendungen mit Process. Start () Gelegentlich wir Erhalten Sie die Ausnahme unten aufgeführt EDIT 1 Nach einigen Inspektion, Heres mehr Details: Launching ist ein 2-Step-Prozess, startet das Launcher ein Zwischenfenster mit Process. WaitForExit () Aus dem Zwischenfenster können weitere Prozesse in der gleichen Weise gestartet werden (Process. WaitForExit). Wenn nur das Zwischenfenster geöffnet ist und keine Benutzerinteraktion, erhöht sich die Anzahl der Griffe im Laufe der Zeit. Der maximale Anstieg weve gesehen hier ist 400 - 6000 Griffe. Die Tatsachen, die im Edit hinzugefügt wurden, lassen mich wirklich fragen, ob es irgendwo ein Griffleck im Framework geben könnte. Ich versuche, das Problem zu isolieren und zu überprüfen, ob ich es von Grund auf neu zu reproduzieren. In der Zwischenzeit wird jede Art von Hinweis, Idee, Unterstützung oder sogar Schokolade gerne angenommen EDIT 2. In einem Versuch, den Prozess auf PostMessage () zu reagieren. Haben wir die Thread. WaitForExit entfernt. Stattdessen fügten wir einen Handler für die Processs Exited-Ereignis und schickte den Launcher in eine Schleife wie die folgenden: Der Exited-Handler setzt foo auf false und tut nichts anderes. Dennoch steigt die Anzahl der Handles (400 bis 800 in einer halben Stunde). EDIT 3 Hier kommt etwas Interessantes, endlich. Das hält es so, wie es sein soll, wenige Handgriffe, alles schick. Jetzt frage ich mich, was hier falsch ist. Ill reden mit dem Entwickler verantwortlich wieder zu überprüfen, was sonst der Trägerrakete tut. Bisher habe ich gehört, dass es einige Config-Werte mit XmlDocument. Load () liest. Die nicht eine IDisposable ist - macht es schwer, irgendwelche Leckagen hier zu produzieren. Gefragt 10.04.2004 um 10:25Multistage Prozesse mit der OmniThreadLibrary Die OtlParallel Unit in der OmniThreadLibrary bietet einige High-Level-Lösungen, mit denen Sie problemlos einige Arten von Prozessen parallel ausführen können. Bisher unterstützte es autarke Hintergrundberechnungen (Parallel. Future), unabhängige Parallelprozesse (Parallel. Join) und Loopberechnungen, bei denen die Hintergrundaufgabe stateless ist (dh sie hängt nur von der Eingabe 8211 des Schleifenwertes 8211 und nicht von Berechnungen ab An anderen Eingängen ausgeführt 8211 Schleifenwerte Parallel. ForEach). Aber viele Zeitprozesse fallen in diese Kategorien. Mason Wheeler hat kürzlich vorgeschlagen, Unterstützung für mehrstufige Prozesse hinzuzufügen. Über das Wochenende I8217ve implementiert es in der OmniThreadLibrary und jetzt diese Funktion ist bereit für Sie zu testen beginnen. Vielen Dank an Mason für seinen Vorschlag und auch für die Arbeit an der Implementierung und dem Design der neu eingeführten Parallel. Pipeline. Die Annahme ist, dass das Verfahren in Stufen (oder Suprocesses) aufgeteilt werden kann, die mit Datenwarteschlangen verbunden sind. Daten fließen von der (optionalen) Eingangswarteschlange in die erste Stufe, wo sie teilweise verarbeitet und dann in die Zwischenwarteschlange emittiert wird. Die erste Stufe setzt dann die Ausführung fort, verarbeitet mehr Eingangsdaten und gibt mehr Ausgangsdaten aus. Dieser Vorgang wird fortgesetzt, bis die gesamte Eingabe bearbeitet ist. Die Zwischenwarteschlange führt in die nächste Stufe, die die Verarbeitung in einer ähnlichen Weise und so weiter und weiter durchführt. Am Ende werden die Daten in eine Warteschlange ausgegeben, die dann von dem Programm gelesen und verarbeitet werden kann, das diesen mehrstufigen Prozess erzeugt hat. Als Ganzes funktioniert ein mehrstufiger Prozess als Pipeline 8211 Daten kommen herein, Daten kommen heraus (und ein Wunder geschieht dazwischen). Wichtig hierbei ist, dass keine Bühnenteile mit einer anderen Stufe zustande kommen. Die einzige Interaktion zwischen den Stufen erfolgt mit den Daten, die durch die Zwischenwarteschlangen weitergegeben werden. Die Datenmenge muss jedoch konstant sein. Es ist durchaus möglich, dass eine Stufe mehr oder weniger Daten erzeugt, als sie am Eingang empfangen wurde. In einem klassischen Singlethread-Programm ist der Ausführungsplan für einen mehrstufigen Prozess sehr einfach. In einer Multithread-Umgebung können wir es besser machen. Da die Stufen weitgehend unabhängig sind, können sie parallel ausgeführt werden. Das Einrichten von Aufgaben und Zwischenwarteschlangen ist ein ziemlich einfaches 8211 aber weit von trivialem 8211 Prozess. Es wäre daher am besten, wenn es in irgendeiner Weise automatisiert werden könnte. Das war die allgemeine Idee, dass der Mason zu mir kam und gemeinsam haben wir einen neuen Teil der OmniThreadLibrary 8211 Parallel. Pipeline entwickelt. Parallel. Pipeline Eine Pipeline wird erstellt, indem die Parallel. Pipeline-Funktion aufgerufen wird, die die IOmniPipeline-Schnittstelle zurückgibt. Es gibt zwei überladene Versionen 8211 für die allgemeine Pipeline-Gebäude und eine andere für einfache Pipelines, die don8217t jede spezielle Konfiguration erfordern. Die letztere Version verwendet zwei Parameter 8211 ein Array von Verarbeitungsstufen und eine optionale Eingabeschlange. Die Eingangs-Warteschlange kann verwendet werden, um erste Daten für die erste Stufe bereitzustellen. Es ist auch vollständig gültig, um 8216nil8217 für den Eingangswarteschlangenparameter zu übergeben und die erste Stufe ohne Eingabe auszuführen. Blocking-Sammlungen werden für die Datenwarteschlange in der Parallel. Pipeline-Implementierung verwendet. Stufen werden als anonyme Prozeduren, Prozeduren oder Methoden implementiert, die zwei Warteschlangenparameter 8211 eins für die Eingabe und eine für die Ausgabe verwenden. Außer in der ersten Stufe, in der die Eingabewarteschlange nicht definiert werden kann, werden beide automatisch durch die Pipeline-Implementierung erstellt und an den Stagedelegaten übergeben. Das nächste Codefragment zeigt die einfache Pipeline-Funktion in Aktion. Es ist aus der OmniThreadLibrary Test 41Pipeline entnommen. Parallel. Pipeline akzeptiert ein Array von Stage-Delegaten und gibt IOmniPipeline-Schnittstelle zurück. Run wird dann auf der Schnittstelle aufgerufen, um die Infrastruktur einzurichten, alle Tasks zu starten und die Ausgangswarteschlange zurückzusenden. Das Hauptprogramm wartet auf die letzte Stufe, um ein Ergebnis zu erzeugen, und weil es weiß, wird es genau einen Wert geben, den er darauf warten kann, indem er die Next-Funktion aufruft (die auch vor kurzem implementiert wurde und nur ein einfacher Wrapper um die Take-Funktion ist) . Die volle Leistung der IOmniPipeline-Schnittstelle wird üblicherweise über die parametrierbare Parallel. Pipeline-Funktion aufgerufen. Eingang setzt die Eingabewarteschlange. Wenn sie nicht aufgerufen wird, wird die Eingangswarteschlange nicht zugewiesen und die erste Stufe erhält nil für den Eingangsparameter. Phase fügt eine Pipeline-Stufe hinzu. Stages fügt mehrere Pipeline-Stufen. NumTasks legt die Anzahl der parallelen Ausführungstasks für die Stufe (n) fest, die gerade mit der Stage (s) - Funktion (IOW, Call Stage gefolgt von NumTasks dazu) hinzugefügt wurde. Wenn sie aufgerufen wird, bevor eine Stufe hinzugefügt wird, wird sie die Vorgabe für alle Stufen angeben. Die Anzahl der parallelen Ausführungsaufgaben für eine bestimmte Stufe kann dann noch durch Aufruf von NumTasks nach dem Aufruf der Stage überschrieben werden. Lesen Sie mehr über parallele Ausführung im Abschnitt Parallele Stufen unten. Drossel stellt die Drosselparameter für die Stufe (n) ein, die gerade mit der Bühnenfunktion hinzugefügt wurde. Ebenso wie die NumTask beeinflusst es entweder die globalen Standardwerte oder nur die aktuell hinzugefügten Stufen. Standardmäßig ist die Drosselung auf 10240 Elemente gesetzt. Weitere Informationen finden Sie im Abschnitt Drosselung. Ausführen führt alle harte Arbeit 8211 Warteschlangen und richtet OmniThreadLibrary-Tasks ein. Es gibt die Ausgangswarteschlange zurück, die dann in Ihrem Programm verwendet werden kann, um das Ergebnis der Berechnung zu erhalten. Selbst wenn die letzte Stufe kein Ergebnis erzeugt, kann diese Warteschlange verwendet werden, um das Ende der Berechnung zu signalisieren. Wenn jede Stufe beendet ist, wird CompleteAdding automatisch auf der Ausgangswarteschlange aufgerufen. Dies ermöglicht die nächste Stufe, um das Ende der Eingabe zu ermitteln (das Blockieren des Auflistungs-Enumerators beendet oder TryTake gibt false zurück). Gleiches gilt für die Ausgangswarteschlange. Ein Beispiel (auch aus der 41Pipeline genommen) wird dazu beitragen, dies alles zu erklären. Zuerst wird ein globaler Throttling-Parameter gesetzt. Es wird auf alle Stufen angewendet. Danach werden zwei Stufen hinzugefügt, jeweils mit einem separaten Aufruf der Bühnenfunktion. Anschließend werden zwei Stufen mit einem Aufruf hinzugefügt. Sie werden beide in zwei parallelen Tasks ausgeführt. Am Ende wird eine weitere Stufe hinzugefügt und das gesamte Setup wird ausgeführt. Der gesamte Prozess wird sieben Tasks verwenden (eine für StageGenerate, eine für StageMult2, zwei für StageMinus3, zwei für StageMod5 und eine für StageSum). Generatoren, Mutatoren und Zusammenfassungen Let8217s nehmen einen Blick an drei verschiedenen Beispielen der multiprocessing Stufen, bevor ich eine Wendung für das tiefe Wasser nehme. Das erste Beispiel ist ein Beispiel für eine erste Stufe, die keine Eingabe annimmt und nur eine Ausgabe erzeugt, die an die nächste Stufe in der Kette übergeben wird. (Alle Beispiele werden wieder aus der 41Pipeline genommen.) Das zweite Beispiel liest Daten aus dem Eingang und erzeugt für jeden Eingang einen Ausgangswert. Das letzte Beispiel liest Daten aus der Eingabe, addiert alle Werte zusammen und erzeugt nur einen Summenwert. Alle Beispiele sind nur spezielle Fälle des allgemeinen Prinzips 8211 there8217s keine Korrelation zwischen der Menge der Eingangsdaten und der Menge der Ausgabedaten erforderlich. There8217s auch absolut keine Voraussetzung, dass Daten alle Zahlen sein müssen. Fühlen Sie sich frei, um alles, was in TOmniValue enthalten sein kann passieren. Throttling In meinem Testfall (41Pipeline) wird eine große Menge an Daten (eine Million Nummern) durch den mehrstufigen Prozess geleitet. Wenn ein Thread für einige Zeit unterbrochen wird oder wenn er eine Berechnung ausführt, die langsamer als der vorherige Thread 8211 ist, kann diese thread8217s Eingabewarteschlange mit Daten füllen, die viel Speicher verursachen und später freigeben können. Um auch den Datenfluss, Pipeline Drosseln verwendet. Eine neue Funktionalität in der Sperrsammlung. Throttling setzt die maximale Größe (in TOmniValue-Einheiten) der Sperrsammlung. Wenn die angegebene Menge an Datenposten in der Sammlung gespeichert ist, können keine weiteren Daten hinzugefügt werden. Die Add-Funktion wird einfach blockieren, bis die Sammlung wieder leer ist oder CompleteAdding aufgerufen wurde. Die Sammlung gilt als leer, wenn die Datenanzahl unter einen Wert fällt, der entweder als zweiter Parameter an die Throttle-Funktion übergeben oder als 34 der maximalen Größengrenze berechnet werden kann, wenn der zweite Parameter nicht bereitgestellt wird. Parallele Stufen In der Regel wird für jede Stufe in der Pipeline ein Task gestartet. In einigen speziellen Fällen kann es jedoch wünschenswert sein, mehr als eine parallele Aufgabe für jede Stufe auszuführen. Ein Beispiel dafür wurde oben in der Methode btnExtended2Click angegeben. Die in diesem Beispiel erzeugte Pipeline kann mit folgendem Diagramm dargestellt werden. Wie Sie sehen können, gibt es immer nur eine Warteschlange, die zwischen den Stufen sitzt, auch wenn es mehrere Verarbeitungseinheiten für eine Bühne gibt. Dies ist leicht durch IOmniBlockingCollection unterstützt mehrere Leser und mehrere Autoren in einer threadsicheren Weise erreicht. Es gibt jedoch eine wichtige Einschränkung. Wenn Sie eine Stufe in mehrere Aufgaben aufteilen, werden die Daten in einer unbestimmten Reihenfolge verarbeitet. Sie können nicht wissen, wie viele Elemente von jeder Aufgabe verarbeitet werden und in welcher Reihenfolge sie verarbeitet werden. Noch schlimmer 8211-Daten beenden die Multitask-Stufe in einer unbestimmten Reihenfolge (die Datenausgabe von einem Task wird mit den Daten der anderen Task verschachtelt). Ab diesem Moment gibt es keine Möglichkeit, die ursprüngliche Ordnung durchzusetzen, da dies in der Parallel. ForEach-Implementierung erfolgt. Abgeschlossen oder nicht Obwohl die Parallel. Pipeline begangen worden ist und zum Testen bereit ist, können sie trotzdem einige Quirks im Code sein. I8217ll folgen Sie diesem mit einem oder zwei auf Test und Leistung und Sie können warten, bis dann, bevor Sie es verwenden. Wenn Sie mir mit der Entwicklung helfen wollen, dann gehen Sie bitte voran, verwenden Sie es und melden Sie alle Probleme zurück zu mir, entweder hier in den Kommentaren oder im Forum.

No comments:

Post a Comment