我正在学习.net Rx(Reactive Extensions)库并尝试创建一个从Console中读取用户输入的正确Observable。
到目前为止,我来到这里:
public static IObservable<string> ConsoleInputObservable()
{
return Observable.Create<string>(observer =>
{
var cancelable = new BooleanDisposable();
while(!cancelable.IsDisposed)
{
observer.OnNext(Console.ReadLine());
}
observer.OnCompleted();
return cancelable;
});
}
不幸的是,这个实现至少有一个问题 - 没有办法取消订阅它。
所以我的问题是:如何正确地将一系列阻塞事件转换为Observable?
感谢。
编辑:拼写错误
答案 0 :(得分:3)
你走了。
请注意以下几点:
OnCompleted
,因为终止的唯一方法是取消订阅 - 并且您努力在取消后不再发送消息OnNext
帖子取消。以下是代码:
public static IObservable<string> ConsoleInputObservable(
IScheduler scheduler = null)
{
scheduler = scheduler ?? Scheduler.Default;
return Observable.Create<string>(o =>
{
return scheduler.ScheduleAsync(async (ctrl, ct) =>
{
while(!ct.IsCancellationRequested)
{
var next = Console.ReadLine();
if(ct.IsCancellationRequested)
return;
o.OnNext(next);
await ctrl.Yield();
}
});
});
}
@MartinLiversage评论说,多个订阅者的行为是不可取的 - 这促使了这个附录。您可以简单地Publish()
上面的代码,但鉴于控制台的性质是应用程序只有一个,并且一次只有一个线程可以读取它,因此需要采用不同的方法。
我忽略了上述内容,因为我觉得问题可能更多是关于线程方面而不是控制台的本质。如果您真的有兴趣报告在控制台输入的行,那么某些类似主循环可能更实用 - 这代表Subject
的合理使用。
static void Main()
{
Subject<string> sc = new Subject<string>();
// kick off subscriptions here...
// Perhaps with `ObserveOn` if background processing is required
sc.Subscribe(x => Console.WriteLine("Subscriber1: " + x));
sc.Subscribe(x => Console.WriteLine("Subscriber2: " + x));
string input;
while((input = Console.ReadLine()) != "q")
{
sc.OnNext(input);
}
sc.OnCompleted();
Console.WriteLine("Finished");
}