我希望下面的程序会在您按下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
内放置断点,则可以清楚地看到这一点。您可以让这两个流只共享一个源订阅,即可观察的按键。因此,我们将冷可观察的转换为热的。
-
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; }