Der Code sieht fast so aus: Wie Sie sehen können, startet der Code einen cmd. exe-Prozess und übergibt ihm 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 seine empfohlen, um umgeleitete Ströme vor dem Prozess lesen. WaitForExit (Timeout) Aufruf, auch das ist besonders wahr, 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 für beide 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 Schreiben Sie 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. Elina: Danke für Ihre Antwort. Es gibt einige Notizen am unteren Rand dieses MSDN-Dokuments (msdn. microsoften-uslibraryhellip), die vor potenziellen Deadlocks warnen, wenn Sie das Ende der beiden umgeleiteten Stdout - und Stderr-Streams synchron lesen. Es ist schwer zu sagen, ob Ihre Lösung anfällig für dieses Problem ist. Auch scheint es, dass Sie den Prozess39 stdoutstderr Ausgang rechts zurück als Eingang senden. Warum. ) Ndash Matthew Piatt Dies ist eine moderne, TPL-basierte Lösung (Task Parallel Library, TPL) basierte Lösung für 4.5 und höher. Antwort # 2 am: Juli 12, 2010, 07:10:13 am »Ich Sache, dass dies ist einfach und besser Ansatz (wir brauchen nicht AutoResetEvent): Antwort # 2 am: Mai 12, 2010, 10:12:13 pm» True, aber shouldn39t Sie tun. FileName Pfad quotggsci. exequot lt Obeycommand. txtquot, um Ihren Code zu zu vereinfachen Oder vielleicht etwas gleichbedeutend mit quotecho Befehl quotieren Pfad quotggsci. exequot, wenn Sie wirklich don39t eine separate obeycommand. txt-Datei verwenden möchten. Ndash Amit Naidu Ihre Lösung braucht nicht AutoResetEvent aber Sie Umfrage. Wenn Sie statt der Verwendung von Ereignis (wenn sie verfügbar sind) abstimmen, dann verwenden Sie CPU ohne Grund und dass Sie sind ein schlechter Programmierer. Ihre Lösung ist wirklich schlecht, wenn die anderen mit AutoResetEvent verglichen werden. (Aber ich habe dir nicht gegeben, weil du versucht hast zu helfen). Ndash Eric Ouellet Ich war mit dem gleichen Problem, aber der Grund war anders. Es würde jedoch unter Windows 8, aber nicht unter Windows 7 auftreten. Die folgende Zeile scheint das Problem verursacht haben. Die Lösung war, NICHT deaktivieren UseShellExecute. Ich erhielt nun ein Shell-Popup-Fenster, das unerwünscht ist, aber viel besser als das Programm wartet auf nichts Besonderes passieren. So fügte ich die folgenden Work-around für das: Jetzt ist das einzige, was mich stört, warum dies geschieht unter Windows 8 an erster Stelle. Ich habe versucht, eine Klasse, die Ihr Problem mit Hilfe von asynchronen Stream zu lösen, indem Sie in Konto Mark Byers, Rob, stevejay Antworten lösen würde. Dabei erkannte ich, dass es einen Fehler im Zusammenhang mit asynchrone Prozess-Ausgabe-Stream zu lesen. Sie können das nicht tun: Sie erhalten System. InvalidOperationException. StandardOut wurde nicht weitergeleitet oder der Prozess hat noch nicht begonnen. Danach müssen Sie die asynchrone Ausgabe starten, die nach dem Start des Prozesses gelesen wird. Führen Sie deshalb eine Racebedingung aus, da der Ausgabestream Daten empfangen kann, bevor Sie ihn auf asynchron setzen. Dann könnten einige Leute sagen, dass Sie nur den Stream vor Ihnen lesen müssen Setzen Sie es auf asynchron. Aber das gleiche Problem tritt auf. Es wird eine Racebedingung zwischen dem synchronen Lesen und dem Setzen des Streams in den asynchronen Modus geben. Es gibt keine Möglichkeit, das sichere asynchrone Lesen eines Ausgabestreams eines Prozesses in der eigentlichen Weise zu erledigen. Process und ProcessStartInfo wurden entworfen. Sie sind wahrscheinlich besser mit asynchronen Lesen wie von anderen Benutzern für Ihren Fall vorgeschlagen. Aber Sie sollten sich bewusst sein, dass Sie einige Informationen aufgrund Rasse Zustand verpassen könnte.
No comments:
Post a Comment