문제

이 방법이 있습니다.

    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();
            }
        }
    }

그리고 프로세스 (cmd.exe)에서 스트림을 읽습니다. 사용자가 CMD.EXE 창을 닫으면 CPU 사용이 100%로 이동합니다. 디버거를 가지고 재생할 때 SR.Readline ()에서 멈추고 돌아 오지 않습니다. 이것은 StandardErrorstream과 StandardOutputStream을 모두보고 있기 때문에 두 코어에서 100%를 사용합니다.

필요한 경우 프로젝트 코드가 더 있습니다.

    [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;
        }
    }

또 다른 흥미로운 것은 이것이 CMD 창을 항상 숨기는 것은 아니라는 것입니다. 그것은 처음으로 그것을 숨기고 두 번째 (또는 그 이후) 숨기지 않을 것입니다. 이것은 사용자가 CMD.exe 창을 닫고 읽기 라인이 재미있게 행동하게 할 때입니다. 또한 종료되지 않는 한 CMD에 출력 된 마지막 줄을 읽지 않습니다.

이 문제를 해결하는 방법에 대한 제안이 있습니까?

도움이 되었습니까?

해결책

당신이 가질 때마다 while(true) 코드에서 루프에서 벗어날 수있는 방법이 없다면 CPU (또는 적어도 하나의 코어)를 100%로 잡을 것입니다. 귀하의 경우에는 a가 있습니다 return 진술, 그러나 루프의 어느 시점도 당신은 stop 가변 보호.

다른 팁

나는 바뀔 것이다:

while(true)

에게:

while(!sr.EOS) {

}

루프를 끝내기 위해 확인하는 더 좋은 방법입니다.

이것은 여기서 흥미로운 문제처럼 보입니다. 언뜻보기에, 읽기 라인은 데이터를 읽으려고하는 동안 손잡이가 닫히는 데 문제가있는 것으로 보이므로 프레임 워크의 버그 인 것 같습니다. 그러나, 나는 그것이 .NET 프레임 워크의 버그라고 쉽게 확신하지 못합니다 ...

그러나 여기에는 몇 가지 낮은 수준의 문제가 있습니다.

지금까지 얻은 다른 답변은 모두 while 루프를 수정하는 것을 제안합니다. 나는 이것도 할 것이지만, 이것이 당신의 문제의 근본이라고 생각하지 않습니다. 읽을 데이터가 없으면 akestate를 읽을 수없고, 단지 실패를 반환하면 '꽉 루프'됩니다. 따라서이 루프 중에 모든 오류 상태를 확인하고 있는지 확인하십시오.

그렇지 않으면 문제를 볼 수 있습니다.

다른 모든 것이 그대로 작동한다면, 내가 당신이라면, 나는 당신이 작은 데모 프로그램으로 프로그램 밖에서 복제 할 수 있는지 식별하려고 노력할 것입니다. 프레임 워크의 스트림 처리에 많은 오류 확인이 있다고 확신합니다. 그러나 Cygwin에서 물건을 실행하는 것처럼 보이며 CMD 쉘에서 읽는 출력입니다.

데이터를 stdout과 stderr에 뱉어내는 간단한 앱을 만들어 보았습니다. 그런 다음 여전히 읽는 동안 앱이 닫히도록하십시오.

또한 디버거를 사용하여 실패가 발생한 후 어떤 줄 ==를 확인하십시오.

래리

was while(true) 루프에서 수면이 없으면 100% CPU 사용이 발생합니다.

CPU가 다른 일을 할 수 있도록 어느 시점에서 어느 시점에서 잠을 자거나 어느 시점에서 루프에서 벗어나야합니다.

최소한 당신은 다음의 선을 따라 무언가를해야합니다.

while (sr.Peek() >= 0) 
{
    Console.WriteLine(sr.ReadLine());
    Thread.Sleep(0);
}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top