我有这个方法:
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窗口并使readline行为有趣的时候.它也永远不会读取输出到cmd的最后一行,除非它退出.
对于如何解决这个问题,有任何的建议吗?
我会改变:
while(true)
至:
while(!sr.EOS) { }
这是检查结束循环的更好方法.
每当你while(true)
的代码中有一个循环时,你将以100%的方式将你的cpu(或至少一个核心)挂起,除非你还有办法摆脱循环.在你的情况下,你有一个return
声明,但在循环中没有任何一点你做任何stop
保护它的变量.