我想知道是否有办法采用可观察的流并使用* While运算符,特别是TakeWhile,SkipWhile和BufferWhile,以便当bool'while'条件满载时,它们的订阅者不会收到.OnComplete ?
当我开始使用.TakeWhile / SkipWhile和BufferWhile操作符时,我认为它们不会终止/ .OnComplete()但只是(不)在满足bool条件时发出。
通过一个例子可能更有意义:
我有一个bool标志,指示实例是否忙,以及一个Observable数据流:
private bool IsBusy { get;set; }
private bool IgnoreChanges { get;set; }
private IObservable<int> Producer { get;set; }
private IDisposable ConsumerSubscription { get;set; }
..并使用/设置RX流(简化)
private void SetupRx()
{
ConsumerSubscription = Producer
.SkipWhile(_ => IgnoreChanges == true) // Drop the producer's stream of ints whenever the IgnoreChanges flag is set to true, but forward them whenever the IgnoreChanges flag is set to false
.BufferWhile(_ => IsBusy == true) // for all streamed instances buffer them as long as we are busy handling the previous one(s)
.Subscribe(i => DoSomething(i));
}
private void DoSomething(int i)
{
try
{
IsBusy = true;
// ... do something
}
finally
{
IsBusy = false;
}
}
只要IsBusy / IgnoreChanges标志从true切换为false并返回,但.SkipeWhile / .BufferWhile不应完成/ OnComplete(..),但保持流存活。
开箱即用的RX.Net在某种程度上是可行的和/或有人知道如何实现这个目标吗?
答案 0 :(得分:5)
要从OnCompleted
来源中删除IObservable<T>
消息,只需Concat
Observable.Never<T>()
:
source.TakeWhile(condition).Concat(Observable.Never<T>())
要手动订阅IObservable<T>
来源,只有在您手动取消订阅时订阅才会结束,您可以使用Publish
和IConnectableObservable<T>
:
var connectableSource = source.Publish();
// To subscribe to the source:
var subscription = connectableSource.Connect();
...
// To unsubscribe from the source:
subscription.Dispose();
所有这一切,我认为你正在接近这个错误。如果操作正确,您将不再需要上述技巧。看看你的问题:
ConsumerSubscription = Producer
// Drop the producer's stream of ints whenever the IgnoreChanges flag
// is set to true, but forward them whenever the IgnoreChanges flag is set to false
.SkipWhile(_ => IgnoreChanges == true)
// For all streamed instances buffer them as long as we are busy
// handling the previous one(s)
.BufferWhile(_ => IsBusy == true)
.Subscribe(i => DoSomething(i));
您应该使用.Where(_ => !IgnoreChanges)
代替.SkipWhile(_ => IgnoreChanges)
。
您应该.Buffer(_ => IsBusy.SkipWhile(busy => busy))
使用BehaviorSubject<bool> IsBusy
代替.BufferWhile(_ => IsBusy)
。
完整的代码如下所示:
private BehaviorSubject<bool> IsBusy { get;set; }
private bool IgnoreChanges { get;set; }
private IObservable<int> Producer { get;set; }
private IDisposable ConsumerSubscription { get;set; }
private void SetupRx()
{
ConsumerSubscription = Producer
.Where(_ => !IgnoreChanges)
.Buffer(_ => IsBusy.SkipWhile(busy => busy))
.Subscribe(buffer => DoSomething(buffer));
}
private void DoSomething(IList<int> buffer)
{
try
{
IsBusy.OnNext(true);
// Do something
}
finally
{
IsBusy.OnNext(false);
}
}
下一个改进是试图摆脱BehaviorSubject<bool> IsBusy
。主题是你想要避免的东西,因为它们是你必须管理的状态。