我有两个可观察者。一个来自Observable.fromEvent(..)
,其中基础事件是用户检查Winforms复选框。另一个是Observable.Interval(..)
,我为了做一些IO而订阅了,我想在没有选中复选框的情况下阻止这个observable执行IO。
我可以这样做:
var gui = new GUI();
var booleans = Observable
.FromEvent<GUI.NewAllowHandler, bool>(
h => gui.NewAllow += h,
h => gui.NewAllow -= h)
Observable.Interval(TimeSpan.FromSeconds(10))
.CombineLatest(booleans, Tuple.Create)
.Where(t => t.Item2)
.Select(t => t.Item1)
.Subscribe(l => DoStuff(l));
但是这有将混合布尔进出流的开销。如果我可以从booleans
变量生成一个时变值,那么更好的方法是这样做,它始终具有最后一个事件的值。然后我可以这样做:
var gui = new GUI();
var booleanState = Observable // typeof(booleanState) == ???
.FromEvent<GUI.NewAllowHandler, bool>(
h => gui.NewAllow += h,
h => gui.NewAllow -= h)
.TimeValue() // hypothetical syntax
Observable.Interval(TimeSpan.FromSeconds(10))
.Where(_ => booleanState)
.Subscribe(l => DoStuff(l));
,这对我来说似乎更接近问题陈述。在Rx中有没有这样的东西,或者还有什么东西可以让这些问题更容易处理?
答案 0 :(得分:2)
您的时间间隔中的Where
语句应该适用于正常范围的普通bool:
var booleans = Observable
.FromEvent<GUI.NewAllowHandler, bool>(
h => gui.NewAllow += h,
h => gui.NewAllow -= h)
var isBoxChecked = false;
booleans.Subscribe(t => isBoxChecked = t);
Observable.Interval(TimeSpan.FromSeconds(10))
.Where(_ => isBoxChecked)
.Subscribe(l => DoStuff(l))
编辑:根据您的评论,另一种方式:
intervals = Observable.Interval(TimeSpan.FromSeconds(10));
booleans
.Where(t => t)
.SelectMany(_ => intervals.TakeUntil(booleans))
.Subscribe(l => DoStuff(l))
答案 1 :(得分:1)
您需要将复选框选中状态建模为行为而不是事件流(因为行为始终具有值,并且此值会在一段时间内发生变化 - 这与复选框选中状态相符)。所以你可以这样做:
var booleans = new BehaviorSubject<bool>(chk.Checked)
var chkEvents = ... //generate boolean observable from checkbox check event
chkEvents.Subscribe(booleans);
Observable.Interval(TimeSpan.FromSeconds(10))
.Where(i => booleans.First())
.Subscribe(i => DoIO());
答案 2 :(得分:1)
我打算给你两个解决方案。第一个是一个非常简单,有希望显而易见的只使用一个可观察的。第二个是使用两个可观察量。
由于您只想在选中此框时允许IO,因此这是最简单的方法:
Observable
.Interval(TimeSpan.FromSeconds(10))
.Where(_ => gui.IsChecked)
.Subscribe(l => DoStuff(l));
根本不需要其他可观察物。
但如果你真的需要使用它,那么Switch()
扩展方法是你最好的选择。试试这个:
booleans
.Select(b => b == true
? Observable.Interval(TimeSpan.FromSeconds(10))
: Observable.Empty<long>())
.Switch()
.Subscribe(l => DoStuff(l));
它很干净,如果没有勾选复选框,有助于显示空白时段。
我希望这会有所帮助。