我正在测试尝试测试RX并创建Stream(),它提供两个相隔1秒的事件。
private IObservable<string> Stream()
{
return Observable.Create<string>
(
(IObserver<string> observer) =>
{
observer.OnNext("a");
observer.OnNext("b");
observer.OnCompleted();
return Disposable.Create(() => Console.WriteLine("Observer has unsubscribed"));
}
);
}
_refreshFiberStream =
Stream()
.SubscribeOn(schedulerProvider.EventLoop)
.Select(DoCalc)
.ObserveOn(schedulerProvider.Dispatcher)
.Subscribe(Update);
和ScheduleProvider
public sealed class SchedulerProvider : ISchedulerProvider
{
public IScheduler Dispatcher
{
get { return DispatcherScheduler.Current; }
}
public IScheduler EventLoop
{
get { return new EventLoopScheduler(); }
}
// ...
}
我看到每个输入都会调用DoCalc方法两次,然后调用两次Update方法,DoCalc,DoCalc,Update,Update。相反,我试图按顺序排序DoCalc方法,然后是Update方法。重复序列进行第二次输入,因此第二个输入可以构建在第一个输入,DoCalc,Update,DoCalc,Update
的结果之上任何想法
答案 0 :(得分:0)
首先,我会遵循在最终的Subscribe方法之前放置SubscribeOn / ObserveOn对的模式。这样可以省去很多毛发。
_refreshFiberStream = Stream()
.Select(DoCalc)
//Always in this pattern
.SubscribeOn(schedulerProvider.EventLoop) //SubscribeOn right before ObserveOn (or before Subscribe if no ObserveOn is used)
.ObserveOn(schedulerProvider.Dispatcher) //ObserveOn right before Subscribe
.Subscribe(Update); //Subscribe Last
接下来,如果我重新创建您的示例并添加丢失的代码,我会得到正确/预期的输出。
void Main()
{
var els = new EventLoopScheduler();
var dispatcher = new EventLoopScheduler();
Stream()
.SubscribeOn(els) //TODO: Move to line just before ObserveOn
.Select(DoCalc)
.ObserveOn(dispatcher)
.Subscribe(Update);
}
// Define other methods and classes here
private IObservable<string> Stream()
{
return Observable.Create<string>
(
(IObserver<string> observer) =>
{
observer.OnNext("a");
Thread.Sleep(1000);
observer.OnNext("b");
observer.OnCompleted();
return Disposable.Create(() => Console.WriteLine("Observer has unsubscribed"));
}
);
}
private string DoCalc(string val)
{
val.Dump("DoCalc()");
Thread.Sleep(1000);
return val;
}
private void Update(string val)
{
val.Dump("Update()");
}
那么你可以用输出重新发布你的完整示例代码吗?这可以作为单元测试,控制台应用程序或LinqPad样本。
猜测你的下一个问题,可能是:我如何使用前一个值的投影值(Select
)来帮助计算下一个值?如果您想要running set of calculations,请使用Scan
方法,如果您只想要最终结果而不是计算每个值,请使用Aggregate
方法。