在Node.js中,您可以设置服务器,只要该服务器在事件循环中处于活动状态并处于活动状态,该过程就不会终止。我想知道是否可以使用反应式扩展做类似的事情?我知道如何设置命名管道并利用它在另一个进程中与Node服务器通信,但是我不确定如何通过等待按键来阻止程序终止。我想将该服务器实现为反应式管道的一部分。在管道完成之前是否可以阻塞主线程?
答案 0 :(得分:0)
open System
open System.Threading
open FSharp.Control.Reactive
module Observable =
/// Blocks the thread until the observable completes.
let waitUnit on_next (o : IObservable<_>) =
use t = new ManualResetEventSlim()
use __ = Observable.subscribeWithCompletion on_next (fun _ -> t.Set()) o
t.Wait()
Observable.interval (TimeSpan.FromSeconds(1.0))
|> Observable.take 3
|> Observable.waitUnit (printfn "%i...")
printfn "Done."
上面使用的是F# Rx bindings,但是C#版本将类似。库本身具有Observable.wait
类型的IObservable<'a> -> 'a
,但是它的缺点是在空序列上引发异常,并在内存中保留最新值,直到可观察的对象被处置为止。如果最终值不重要,则这具有正确的语义。
我已经看过内部,wait
使用ManualResetEventSlim
来阻止它所在的线程,所以应该没事。
答案 1 :(得分:0)
对不起,但是我无法在F#中给出答案,但是在C#中,这非常简单。
如果我有这个示例:
Observable
.Range(0, 10)
.Subscribe(x => Console.WriteLine(x));
...我想等到它完成,我可以这样重写它:
Observable
.Range(0, 10)
.Do(x => Console.WriteLine(x))
.ToArray()
.Wait();
...或:
await Observable
.Range(0, 10)
.Do(x => Console.WriteLine(x))
.ToArray();
正如Marko在评论中指出的那样,这种方法创建的数组可能很大。为了解决这个问题,您可以将.ToArray()
替换为.LastAsync()
(在一般使用Async
之前用它来表示Task
的名称-在这种情况下,它仅返回的最后一个元素可观察为IObservable<T>
)。
.Wait()
确实抛出了一个空的可观察对象,但是await
版本却没有。