[英]System.Diagnostics.Process.Start weird behaviour
我正在编写一个应用程序来启动和监视C#中的其他应用程序。 我正在使用System.Diagnostics.Process类来启动应用程序,然后使用Process.Responding属性监视应用程序,以每100毫秒轮询一次应用程序的状态。 我使用Process.CloseMainWindow来停止应用程序或Process.Kill如果它没有响应就杀死它。
我注意到一种奇怪的行为,有时进程对象进入一种状态,即当底层进程在循环中挂起并且它不响应CloseMainWindow时,响应属性总是返回true。
重现它的一种方法是在启动流程实例后立即轮询Responding属性。 所以举个例子
_process.Start();
bool responding = _process.Responding;
将重现错误状态
_process.Start();
Thread.Sleep(1000);
bool responding = _process.Responding;
将工作。 将睡眠周期减少到500将再次引入错误状态。
启动后调用_process.Responding太快的东西似乎阻止了对象获取正确的Windows消息队列处理程序。 我想我需要等待_process.Start完成它的异步工作。 有没有比调用Thread.Sleep更好的方法来等待这个? 我不太自信1000毫秒总是足够的。
现在,我需要稍后检查一下,但我确信有一个方法告诉线程等待它准备输入。 您是否仅监控GUI流程?
是不是Process.WaitForInputIdle对你有任何帮助? 或者我错过了这一点? :)
在Twitter(或推文推文?)与门德尔聊天之后,我想我应该更新我的答案,以便社区充分了解...
WaitForInputIdle
仅适用于具有GUI的应用程序。 希望有帮助:)
我认为增强对_process.Responding的检查可能会更好,这样如果Responding属性返回false超过5秒(例如),你只会尝试停止/终止进程。
我想你可能会发现,在他们进行更密集的处理时,应用程序可能会在一瞬间“没有响应”。
我相信一种更宽松的方法会更好地工作,允许一个过程在短时间内“没有响应”,只有在几秒钟内(或者你想要多长时间)反复“没有响应”时才采取行动。
进一步说明:Microsoft文档表明Responding属性与用户界面特别相关,这就是新启动的进程可能没有立即响应UI的原因。
谢谢你的回答。 这个
_process.Start();
_process.WaitForInputIdle();
似乎解决了这个问题。 它仍然很奇怪,因为Responding和WaitForInputIdle都应该使用相同的win32 api调用。
更多背景信息
GUI应用程序有一个带有消息队列的主窗口。 Responding和WaitForInputIdle通过检查进程是否仍处理来自此消息队列的消息来工作。 这就是他们只使用GUI应用程序的原因。 不知怎的,似乎调用Responding太快会干扰让Process获取该消息队列的句柄。 调用WaitForInputIdle似乎解决了这个问题。
我将不得不潜入反射器,看看我是否能理解这一点。
更新
似乎在启动后检索与进程关联的窗口句柄足以触发奇怪的行为。 像这样:
_process.Start();
IntPtr mainWindow = _process.MainWindowHandle;
我使用Reflector进行了检查,这就是Responding在幕后所做的事情。 似乎如果你太快得到MainWindowHandle,你会得到错误的一个,并且它会在进程的剩余生命周期中使用这个错误的句柄,或者直到你调用Refresh();
更新
调用WaitForInputIdle()只能在某些时候解决问题。 每次读取Responding属性时调用Refresh()似乎都会更好。
我在大约两年前的一个项目中也注意到了这一点。 在请求某些道具值之前,我调用了.Refresh()。 当我需要调用.Refresh()时,IT是一种试错法。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.