Frage

Ich habe diese Methode:

    private delegate void watcherReader(StreamReader sr);
    private void watchProc(StreamReader sr) {
        while (true) {
            string line = sr.ReadLine();
            while (line != null) {
                if (stop) {
                    return;
                }
                //Console.WriteLine(line);
                line = stripColors(line);
                txtOut.Text += line + "\n";

                line = sr.ReadLine();
            }
        }
    }

Und es liest die Ströme von einem Prozess (cmd.exe). Wenn der Benutzer das cmd.exe-Fenster schließt, verursacht es die CPU-Auslastung auf 100% zu springen. Wenn es mit dem Debugger spielen sehe ich, dass es auf dem sr.ReadLine stoppt () und kehrt nie zurück. Da es sich sowohl die StandardErrorStream beobachten und die StandardOutputStream es 100% auf beiden Kernen verwendet.

Hier ist etwas mehr Code des Projekts, wenn Sie es brauchen.

    [DllImport("User32")]
    private static extern int ShowWindow(int hwnd, int nCmdShow);   //this will allow me to hide a window

    public ConsoleForm(Process p) {
        this.p = p;
        p.Start();
        ShowWindow((int)p.MainWindowHandle, 0);   //0 means to hide the window.

        this.inStream = p.StandardInput;
        this.outStream = p.StandardOutput;
        this.errorStream = p.StandardError;

        InitializeComponent();

        wr = new watcherReader(watchProc);
        wr.BeginInvoke(this.outStream, null, null);
        wr.BeginInvoke(this.errorStream, null, null);
    }

    public void start(string[] folders, string serverPath) {

        this.inStream.WriteLine("chdir C:\\cygwin\\bin");
        this.inStream.WriteLine("bash --login -i");
        this.inStream.WriteLine("");
    }


    //code example from http://geekswithblogs.net/Waynerds/archive/2006/01/29/67506.aspx it is
    //to make the textbox autoscroll I don't understand what it does, but it works.
    #region autoscroll
    [DllImport("User32.dll", CharSet = CharSet.Auto, EntryPoint = "SendMessage")]
    static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);

    const int WM_VSCROLL = 277;
    const int SB_BOTTOM = 7;

    private void txtOut_TextChanged(object sender, EventArgs e) {            
        IntPtr ptrWparam = new IntPtr(SB_BOTTOM);
        IntPtr ptrLparam = new IntPtr(0);
        SendMessage(((RichTextBox)sender).Handle, WM_VSCROLL, ptrWparam, ptrLparam); 
    }
    #endregion

    private void ConsoleForm_FormClosed(object sender, FormClosedEventArgs e) {
        this.stop = true;
        try {
            this.p.Kill();
        } catch (InvalidOperationException) {
            return;
        }
    }

Ein weiterer interessanter ist, dass es nicht immer das cmd Fenster nicht versteckt wie es soll. Er versteckt es das erste Mal, und dann die zweite (oder nach) es wird nicht verbergen. Dies ist, wenn der Benutzer kann das cmd.exe Fenster schließen und die Readline- verursacht lustig zu handeln. Es ist auch nie die letzte Zeile liest ausgegeben cmd es sei denn, es tritt aus.

Alle Vorschläge, wie dieses Problem beheben?

War es hilfreich?

Lösung

Wenn Sie eine while(true) Schleife in Ihrem Code, den Sie gehen, um Ihre CPU (oder zumindest einen Kern) bei 100% peg, wenn Sie auch eine Möglichkeit haben, aus der Schleife zu brechen. In Ihrem Fall haben Sie eine return Erklärung haben, aber an keiner Stelle in der Schleife haben Sie jemals etwas auf die stop Variable tun bewacht es.

Andere Tipps

ich ändern würde:

while(true)

zu:

while(!sr.EOS) {

}

Es ist eine bessere Möglichkeit zu überprüfen, um die Schleife zu beenden.

Das scheint wie ein interessantes Thema hier. Auf den ersten Blick scheint es, dass Readline ein Problem mit dem Griff wird unter ihm geschlossen, während es versucht, Daten zu lesen, und so scheinen würde einen Fehler in der Rahmen zu sein. Aber ich bin nicht davon überzeugt, dass leicht, dass es ein Fehler in der .NET-Framework ist ...

Es gibt jedoch ein paar geringe Probleme hier.

Die anderen Antworten, die Sie bekommen haben bisher alle vorschlagen, dass Sie die while-Schleife ändern. Ich würde auch tun, aber ich glaube nicht, das die Wurzel des Problems ist. Sie brauchen keinen Schlaf drin, weil Sie Ihre Waitstate von der Readline () erhalten werden, es sei denn, es gibt keine Daten, zu lesen ist, und es gibt nur eine failue, dann werden Sie ‚tight-Loop‘. Also, stellen Sie sicher, dass Sie während dieser Schleife jede und alle Fehlerzustände zu überprüfen.

Wenn Sie nicht, ich Probleme sehen können.

Wenn alles andere funktioniert, wie es sollte, dann, wenn ich du wäre, würde ich versuchen, zu identifizieren beginnen, wenn Sie es außerhalb des Programms mit einem kleinen Demo-Programm duplizieren. Ich bin sicher, es gibt viele Fehler im Stream Handling des Rahmen überprüfen. Allerdings sieht es aus wie Sie ein paar Sachen von Cygwin laufen, und das ist die Ausgabe, die Sie aus der cmd Shell lesen.

Versuchen Sie, eine einfache Anwendung zu machen, die nur Daten zu stdout ausspuckt und stderr, und stellen Sie sicher, dass der App schließt, während Sie noch lesen ..

Auch den Debugger verwenden, um zu sehen, welche Zeile == nachdem der Fehler auftritt.

Larry

Mit while(true) ohne Schlaf in der Schleife 100% CPU-Auslastung führen.

Sie müssen sich für eine gewisse Menge an Zeit schlafen oder zu einem bestimmten Zeitpunkt aus der Schleife brechen, so dass die CPU etwas anderes tun können.

Am allerwenigsten sollten Sie etwas entlang der Linien von tun:

while (sr.Peek() >= 0) 
{
    Console.WriteLine(sr.ReadLine());
    Thread.Sleep(0);
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top