我发现了这个极好的答案,它与我要解决的问题非常相似:
Process sometimes hangs while waiting for Exit
尽管我是第一次使用此System.Reactive程序包,所以我在使用和语法方面很挣扎。我正在尝试修改此块以适合我的需求:
var processExited =
// Observable will tick when the process has gracefully exited.
Observable.FromEventPattern<EventArgs>(process, nameof(Process.Exited))
// First two lines to tick true when the process has gracefully exited and false when it has timed out.
.Select(_ => true)
.Timeout(TimeSpan.FromMilliseconds(processTimeOutMilliseconds), Observable.Return(false))
// Force termination when the process timed out
.Do(exitedSuccessfully => { if (!exitedSuccessfully) { try { process.Kill(); } catch {} } } );
我想在超时时检查stdOut缓冲区中的特定字符串,如果找到则退出,否则继续直到下一个超时。但是,我也只想在“放弃”并终止进程之前做很多超时操作,所以在循环中,如果它没有退出,我将增加一个计数器并进行检查。谢谢你的帮助
补充说明,我想要这样的东西:
int timeoutCount = 0;
const int maxTimeoutCount =5;
然后在可观察范围内,类似.Do(成功退出=> {
if (!exitedSuccessfully) {
try {
if (timeoutCount >= maxTimeOutCount || output.ToString().Contains("string_i-m_looking_for_in_output_to_trigger_exit")) {
process.Kill();
}
timeOutCount++;
}
catch { }
}
反应性的基本设计概念是避免状态-声明性地表示行为。在Rx中,您可能需要对传统的变异状态进行建模。
将流程建模为可观察对象的惯用方法是将流程的生存期链接到对可观察对象的订阅。订阅开始该过程,取消订阅停止该过程,反之亦然,退出过程通常完成可观察的过程。
我制作了an implementation of this model on Github。它是C#和F#的单个文件库,它以可观察的方式抽象出标准输入/输出进程。
使用该模型:
StdioObservable
.Create("process.exe")
.TakeUntil(line => line.Contains("Done")) // unsub when you match
.Timeout(TimeSpan.FromSeconds(30)) // no output for 30 seconds
.Catch((Exception exn) => Observable.Empty<string>()) //handle timeout or other
.Subscribe();
[如果您想在一定时间内终止该进程,尽管它会产生一些输出,请使用.Take(TimeSpan.FromSeconds(30))
。