简体   繁体   English

如何循环 Observable Rx 直到满足条件?

[英]How to loop Observable Rx until condition met?

I found this excellent answer that is very similar to the problem I'm trying to solve:我发现这个很好的答案与我要解决的问题非常相似:

Process sometimes hangs while waiting for Exit 等待退出时进程有时会挂起

My first time working with this System.Reactive package though so I'm struggling with the usage and syntax.我第一次使用这个 System.Reactive package 虽然所以我在使用和语法上苦苦挣扎。 I'm trying to modify this block to suit my needs:我正在尝试修改此块以满足我的需要:

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

I would like this to when it times out it checks the stdOut buffer for a particular string, if it finds it then exit, otherwise continue until the next timeout.我希望它在超时时检查 stdOut 缓冲区中的特定字符串,如果找到它则退出,否则继续直到下一次超时。 But also, I only want to do so many timeouts before I 'give up' and kill the process so in the loop, if it doesn't exit, i would increment a counter and check that.而且,我只想在我“放弃”并终止进程之前做这么多超时,所以在循环中,如果它不退出,我会增加一个计数器并检查它。 Thank you for the help感谢您的帮助

Adding clarification, I want something like this:添加说明,我想要这样的东西:

int timeoutCount = 0;
const int maxTimeoutCount =5;

then in the observable, something like.Do(exitedSuccessfully => {然后在 observable 中,类似.Do(exitedSuccessfully => {

          if (!exitedSuccessfully) {
                        try {
                            if (timeoutCount >= maxTimeOutCount || output.ToString().Contains("string_i-m_looking_for_in_output_to_trigger_exit")) {
                                process.Kill();
                            }
                            timeOutCount++;
                        }
                        catch { }
                    }

A fundamental design concept of reactive is to avoid external state - and express behavior declaratively.反应式的基本设计理念是避免外部 state - 并以声明方式表达行为。 In Rx, you might need to model traditionally mutating state differently.在 Rx 中,您可能需要 model 传统上以不同方式变异 state。

An idiomatic way to model a process as an observable is to link the lifetime of the process to subscription to the observable.将进程作为可观察对象的惯用方法是将进程的生命周期链接到对可观察对象的订阅。 Subscribing starts the process, unsubscribing stops the process, and vice versa, the process exiting normally completes the observable.订阅启动进程,取消订阅停止进程,反之亦然,正常退出的进程完成了 observable。

I've made an implementation of this model on Github .我已经在Github 上实现了这个 model It's a single file library for C# and F# which abstracts the std in/out of a process as an observable.它是 C# 和 F# 的单个文件库,它将进程的标准输入/输出抽象为可观察的。

Using that model:使用 model:

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

If you want to kill the process within a duration, in spite of it producing some output, use .Take(TimeSpan.FromSeconds(30)) instead.如果您想在一段时间内终止该进程,尽管它会产生一些 output,请改用 .Take .Take(TimeSpan.FromSeconds(30))

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM