我期望下面的程序能够回显任何按键,直到你点击z
,但是当你点击z
时它不会终止,并且只会在每次按键时回显。我做错了什么?
using System.Reactive;
using System.Reactive.Linq;
public class Printer : IObserver<char>
{
public void OnNext(char x)
{
Console.WriteLine(x);
}
public void OnError(Exception x)
{
}
public void OnCompleted()
{
}
}
class Program
{
static IObservable<char> keys = Observable.Defer(() =>Observable.Start(() =>Console.ReadKey().KeyChar)).Repeat(); //https://stackoverflow.com/questions/10675451/iobservable-of-keys-pressed
public static int Main()
{
IObserver<char> x = new Printer();
keys.Subscribe(x);
keys.Where(b => b == 'z').Wait();
return 0;
}
}
好的,所以两个问题都是分开的:
IEnumerable
每次尝试获取物品时的评估方式。如果你在Observable.Defer
中放置一个断点,你可以清楚地看到这一点。
您可以拥有这两个流share just one subscription to the source,即按键可观察。所以我们将冷观察变为热点。Wait
方法是:
等待可观察序列完成并返回序列的最后一个元素。如果序列以OnError通知终止,则抛出异常。
因此,它将等到序列完成,即,OnCompleted
已被调用可观察链。因此,我们使用TakeUntil
,以便只有在满足条件时才按顺序完成(按'z')。
public static int Main()
{
var keys_stream = keys.Publish().RefCount(); // share
IObserver<char> x = new Printer();
keys_stream.Subscribe(x);
keys_stream.TakeUntil(b => b == 'z').Wait(); //wait until z
return 0;
}