System.Diagnostics.Process.Start seltsames Verhalten

8

Ich schreibe eine Anwendung, um andere Anwendungen in C # zu starten und zu überwachen. Ich verwende die System.Diagnostics.Process-Klasse, um Anwendungen zu starten, und überwache dann die Anwendungen mithilfe der Process.Responding-Eigenschaft, um den Status der Anwendung alle 100 Millisekunden abzufragen. Ich verwende Process.CloseMainWindow, um die Anwendung zu stoppen, oder Process.Kill, um sie zu beenden, wenn sie nicht reagiert.

Ich habe ein seltsames Verhalten bemerkt, bei dem das Prozessobjekt manchmal in einen Zustand gerät, in dem die antwortende Eigenschaft immer true zurückgibt, selbst wenn der zugrunde liegende Prozess in einer Schleife hängt und nicht auf CloseMainWindow reagiert.

Eine Möglichkeit, diese zu reproduzieren, besteht darin, die Respond-Eigenschaft direkt nach dem Start der Prozessinstanz abzufragen. So zum Beispiel

%Vor%

reproduziert den Fehlerzustand während

%Vor%

funktioniert. Wenn Sie den Ruhezustand auf 500 reduzieren, wird der Fehlerzustand erneut eingeführt.

Etwas beim Aufruf von _process.Responding zu schnell nach dem Starten scheint zu verhindern, dass das Objekt den richtigen Windows Message Queue Handler bekommt. Ich denke, ich muss auf _process warten. Starten Sie die asynchrone Arbeit zu beenden. Gibt es einen besseren Weg, darauf zu warten, als Thread.Sleep aufzurufen? Ich bin nicht allzu zuversichtlich, dass die 1000 ms immer ausreichen werden.

    
Mendelt 24.09.2008, 07:58
quelle

4 Antworten

8

Nun muss ich das später überprüfen, aber ich bin mir sicher, dass es eine Methode gibt, die dem Thread sagt, dass er warten soll, bis er für die Eingabe bereit ist. Überwachen Sie nur GUI-Prozesse?

Ist Process.WaitForInputIdle keine Hilfe für Sie? Oder verpasse ich den Punkt? :)

Aktualisieren

Nach einem kurzen Chat auf Twitter (oder Tweet-Tweet?) mit Mendelt dachte ich, ich sollte meine Antwort aktualisieren, damit die Community sich dessen bewusst ist.

  • WaitForInputIdle funktioniert nur bei Anwendungen mit einer GUI.
  • Sie geben die Wartezeit an, und die Methode gibt eine bool zurück, wenn der Prozess innerhalb dieses Zeitrahmens einen Leerlaufzustand erreicht. Sie können diese Schleife natürlich bei Bedarf verwenden oder entsprechend behandeln.

Hoffe das hilft:)

    
Rob Cooper 24.09.2008, 08:19
quelle
4

Ich denke, es ist vielleicht besser, die Prüfung auf _process.Responding zu verbessern, so dass Sie nur versuchen, den Prozess zu stoppen / zu beenden, wenn die Responding-Eigenschaft für mehr als 5 Sekunden (zum Beispiel) false zurückgibt.

Ich denke, Sie werden feststellen, dass Anwendungen oft für einen Bruchteil einer Sekunde "nicht reagieren", während sie eine intensivere Verarbeitung durchführen.

Ich glaube, ein nachsichtiger Ansatz wird besser funktionieren, was es einem Prozess ermöglicht, für eine kurze Zeit "nicht zu reagieren", nur Maßnahmen zu ergreifen, wenn er mehrere Sekunden lang wiederholt (oder wie lange Sie wollen) .

Weitere Hinweise: Die Microsoft-Dokumentation zeigt an, dass sich die Responding-Eigenschaft speziell auf die Benutzeroberfläche bezieht. Aus diesem Grund reagiert die Benutzeroberfläche möglicherweise nicht sofort auf einen neu gestarteten Prozess.

    
Jarod Elliott 24.09.2008 08:08
quelle
3

Danke für die Antworten. Das

%Vor%

Scheint das Problem zu lösen. Es ist immer noch seltsam, weil Reagieren und WaitForInputIdle beide den gleichen win32 API-Aufruf unter den Abdeckungen verwenden sollten.

Einige weitere Hintergrundinformationen GUI-Anwendungen haben ein Hauptfenster mit einer Nachrichtenwarteschlange. Reagieren und WaitForInputIdle funktionieren, indem Sie überprüfen, ob der Prozess weiterhin Nachrichten aus dieser Nachrichtenwarteschlange verarbeitet. Aus diesem Grund arbeiten sie nur mit GUI-Apps. Irgendwie scheint es so zu sein, dass der Aufruf von Reagieren zu schnell dazu führt, dass der Prozess ein Handle für diese Nachrichtenwarteschlange erhält. Der Aufruf von WaitForInputIdle scheint dieses Problem zu lösen.

Ich muss in den Reflektor tauchen, um zu sehen, ob ich das verstehen kann.

update
Es scheint, dass das Abrufen des Fensterhandles, das dem Prozess unmittelbar nach dem Start zugeordnet ist, ausreicht, um das seltsame Verhalten auszulösen. So:

%Vor%

Ich habe es mit Reflector überprüft und dies geschieht unter den Abdeckungen. Es scheint, dass wenn Sie das MainWindowHandle zu früh bekommen, Sie das falsche bekommen und es verwendet dieses falsche Handle es für den Rest der Lebensdauer des Prozesses oder bis Sie Refresh () aufrufen;

update
Der Aufruf von WaitForInputIdle () löst das Problem nur teilweise. Der Aufruf von Refresh () bei jedem Lesen der Antwort-Eigenschaft scheint besser zu funktionieren.

    
Mendelt 24.09.2008 09:08
quelle
1

Das habe ich auch in einem Projekt vor ungefähr zwei Jahren bemerkt. Ich rief .Refresh () auf, bevor ich bestimmte Prop-Werte anforderte. Es war eine Versuch-und-Irrtum-Methode, um herauszufinden, wann ich .Refresh () aufrufen musste.

    
GregUzelac 18.10.2008 01:50
quelle

Tags und Links