Waitforexit Asynchron

Der Code sieht fast so aus: Wie Sie sehen können, startet der Code einen cmd. exe-Prozess und übergibt an ihn den Befehl, den ich ausführen möchte. Ich umleiten StandardError und StandarOutput, um sie aus dem Code zu lesen. Der Code liest sie vor dem Prozess. WaitForExit (Timeout), wie von Microsoft empfohlen (mehr dazu später). Das Problem tritt auf, wenn der Befehl, den ich an cmd. exe sendet, niemals endet oder hängt unbegrenzt. Im Code verwendete ich den Befehl ping - t 8.8.8.8, der wegen der Option - t den Host ohne Stopp pingt. Was passiert Der Befehl cmd. exe zusammen mit dem Befehl ping - txt wird nie beendet und der Stdout-Stream wird nie geschlossen, und daher hängt unser Code an der Ausgabe process. StandardOutput. ReadToEnd () Zeile, weil es nicht gelingt, den gesamten Stream zu lesen. Das gleiche passiert auch, wenn ein Befehl in einer Batch-Datei aus irgendeinem Grund hängt und so der obige Code könnte kontinuierlich arbeiten für Jahre und dann hängen plötzlich ohne ersichtlichen Grund. Bevor ich schrieb, dass es empfohlen, um umgeleitete Streams vor dem Prozess lesen. WaitForExit (Timeout) Aufruf, auch dies gilt insbesondere, wenn Sie die WaitForExit Signatur ohne das Timeout verwenden. Wenn Sie Prozess aufrufen. WaitForExit (), bevor Sie die umgeleiteten Datenströme lesen: code 2: Sie können einen Deadlock erleben, wenn der Befehl, den Sie an cmd. exe anhängen, oder der Prozess, den Sie aufrufen, die Standardausgabe oder Standardfehler erfüllt. Dies, weil unsere Code cant erreichen die Linien Output-Prozess. Standardausgang. ReadToEnd () In der Tat der Kind-Prozess (die Ping-Befehl oder eine Batch-Datei oder was auch immer Sie ausführen) cant gehen auf, wenn unser Programm nicht lesen Sie die gefüllten Puffer der Streams und dies kann passieren, weil der Code hängt Die Linie mit Prozess. WaitForExit (), die immer warten wird, bis das untergeordnete Projekt beendet wird. Die Standardgröße beider Streams beträgt 4096 Byte. Sie können diese beiden Größen mit diesen Batchdateien testen: Das erste Skript schreibt 4096 Byte zur Standardausgabe und das zweite zu Standardfehler. Speichern Sie eine davon in C: testbuffsize. bat und führen Sie unseren Programmaufruf aus. WaitForExit () vor Ausgabeprozess. Standardausgang. ReadToEnd () wie in Code 2. Können Sie es Schreiben CommandResult Ergebnis ExecuteShellCommandSync (c: testbuffsize. bat, 1000) in Zeile 13 von Code 1. Der Code wird nicht hängen, aber wenn Sie schreiben ein weiteres Byte in einem der beiden Streams wird es überlaufen die Puffergröße, die das Programm aufhängen. Wenn Sie die Standardausgabe oder Standardfehler umleiten und lesen müssen, ist die beste Lösung, sie asynchron zu lesen. Eine hervorragende Möglichkeit, dies zu tun, wird von Mark Byers in diesem Stackoverflow-Thread vorgeschlagen Als das letzte, beachten Sie bitte, dass, wenn der untergeordnete Prozess beendet, nur weil Sie den Prozess verwenden. WaitForExit (Timeout) Signatur und es tatsächlich geht in Timeout sollten Sie töten die cmd. exe Prozess und seine möglichen Kinder. Wie verwenden Process. Start in Visual Basic. NET Von Dan Mabbutt. Visual Basic-Experte Die Start-Methode des Process-Objekts ist möglicherweise eines der am meisten geschätzten Werkzeuge, die Ihnen als Programmierer zur Verfügung stehen. Als eine. NET-Methode hat Start eine Reihe von Überladungen (verschiedene Sätze von Parametern, die genau bestimmen, was die Methode tut). In diesem Fall können Sie mit den Überladungen nahezu jeden Satz von Parametern angeben, den Sie an einen anderen Prozess übergeben möchten, wenn er gestartet wird. Was Sie mit Process. Start tun können, ist wirklich nur durch die Prozesse begrenzt, die Sie mit ihm verwenden können. Lesen Sie weiter unten, was zu sagen ist, gibt es kein Limit seit mehr kommen immer die ganze Zeit. Wenn Sie Ihre textbasierte 34ReadMe34-Datei im Editor anzeigen möchten, ist it39s so einfach wie: Dies setzt voraus, dass sich die ReadMe-Datei im selben Ordner wie das Programm befindet und dass Notepad die Standardanwendung für. txt-Dateitypen und it39s in der Systemumgebung ist Pfad. Für die VB639ers im Publikum ist Process. Start etwas wie der VB6 Shell Befehl. In VB6, könnten Sie etwas wie: lngPID 61 Shell (34MyTextFile. txt34, vbNormalFocus) Sie können noch den Shell-Befehl in VB. NET, aber ich wouldn39t es empfehlen. Verwenden Sie stattdessen Process. Start. Sie können diesen Code stattdessen verwenden, um den Editor zu maximieren und ein ProcessStartInfo-Objekt zu erstellen, das Sie für eine präzisere Steuerung verwenden können: Dim ProcessProperties als neues ProcessStartInfo ProcessProperties. FileName 61 34myTextFile. txt34 ProcessProperties. WindowStyle 61 ProcessWindowStyle. Maximized Dim myProcess Als Prozess 61 Process. Start (ProcessProperties) Lesen Sie weiter unten Sie können sogar einen versteckten Prozess starten. ProcessProperties. WindowStyle 61 ProcessWindowStyle. Hidden Aber seien Sie vorsichtig. Es sei denn, Sie fügen Sie mehr Code, um den Prozess zu beenden, müssen Sie es wahrscheinlich im Task-Manager beenden. Hidden Prozesse sind in der Regel nur mit Prozessen, die don39t haben jede Art von einer Benutzeroberfläche verwendet. Arbeiten mit Process. Start als ein. NET-Objekt gibt Ihnen eine Menge von Funktionen. Sie können beispielsweise den Namen des Prozesses abrufen, der gestartet wurde. Dieser Code wird 34notepad34 im Ausgabefenster anzeigen: Dim myProcess als Prozess 61 Process. Start (34MyTextFile. txt34) Console. WriteLine (myProcess. ProcessName) Wenn Sie die Ausführung des Programms bis zum Ende des Prozesses unterbrechen müssen (etwas, was Sie tun könnten Mit API-Code in VB6), hier ya gehen. Console. WriteLine (34Notepad beendet: 34 amp myProcess. ExitTime amp Environment. NewLine amp 34Exit Code: 34 amp myProcess. ExitCode) Dies war etwas, was Sie nicht mit dem Befehl VB6 Shell tun konnte, weil es die neue Anwendung asynchron gestartet. Die Verwendung von WaitForExit kann das umgekehrte Problem in. NET verursachen, da Sie einen Prozess in einem neuen Thread starten müssen, wenn Sie es benötigen, um asynchron auszuführen. Wenn Sie zum Beispiel die Komponenten benötigen, um in einem Formular aktiv zu bleiben, in dem ein Prozess gestartet wurde und WaitForExit ausgeführt wurde. Normalerweise werden diese Komponenten nicht aktiv. Code it up und sehen Sie selbst. Eine Möglichkeit, den Prozess zu stoppen, ist, die Kill-Methode zu verwenden. Dieser Code wartet für zehn Sekunden und beendet den Prozess. Ich fand, dass eine erzwungene Verzögerung war notwendig, damit der Prozess zu beenden Exiting, um einen Fehler zu vermeiden. MyProcess. WaitForExit (10000) 39 Wenn der Prozess doesn39t innerhalb von 39 10 Sekunden abgeschlossen ist, töten Sie es If Not myProcess. HasExited Dann myProcess. Kill () Ende If Threading. Thread. Sleep (1) Console. WriteLine (34Notepad beendet: 34 amp myProcess. ExitTime amp Environment. NewLine amp 34Exit Code: 34 amp myProcess. ExitCode) In den meisten Fällen ist es wahrscheinlich eine gute Idee, Ihre Verarbeitung in einem Block verwenden, um sicherzustellen, dass die Ressourcen, die von dem Prozess freigegeben werden. Verwenden von myProcess als Prozeß 61 Neuer Prozeß 39 Ihr Code geht hier Ende Verwenden Um dies alles noch einfacher zu gestalten, gibt es sogar eine Prozesskomponente, die Sie zu Ihrem Projekt hinzufügen können, so dass Sie viele der oben beim Design gezeigten Dinge tun können Zeit statt der Laufzeit. Eines der Dinge, die dies macht viel einfacher ist die Codierung von Ereignissen, die durch den Prozess, wie das Ereignis, wenn der Prozess verlassen hat. Sie können auch einen Handler mit Code wie folgt hinzufügen. 39 erlauben dem Prozess, die Ereignisse zu erhöhen myProcess. EnableRaisingEvents 61 True 39 einen Exited-Ereignishandler hinzufügen AddHandler myProcess. Exited, AddressOf Me. ProcessExited Private Sub ProcessExited (ByVal-Absender als Objekt, ByVal und als System. EventArgs) 39 Ihr Code geht hier End Sub Aber einfach die Auswahl der Veranstaltung für die Komponente ist viel einfacher.


Comments