我希望下面的程序在您按下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;
}
}
答案 0 :(得分:2)
好的,所以两个问题都分开了:
您在这里拥有的是cold observable。
只有当您开始观察它时,它才会产生值。
相反,每次订阅时,它代表一个新流-类似于IEnumerable
每次尝试取物品时的评估方式。如果在Observable.Defer
内放置一个断点,则可以清楚地看到这一点。
您可以拥有这两个流share just one subscription to the source,即可以观察到的按键。因此,我们将可观测的寒冷转化为炎热的天气。
Wait
方法是:
等待可观察到的序列 complete ,并返回的最后一个元素 序列。如果序列以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;
}