让我们考虑以下流
SomeState state = new SomeState().
_refreshFiberStream =
Stream()
.SubscribeOn(new EventLoopScheduler())
.Select(DoCalc)
.ObserveOn(DispatcherScheduler.Current)
.Subscribe(Update);
DoCalc方法将投射到输入并消耗“状态”。并将结果输出提供给Update方法,这将修改'状态'。如果有新事件发生,它应该根据上次事件的最后更新状态,并根据该事件进行项目。
我正在寻找一种总是按顺序执行事件的方法。例如,如果我有三个事件,我正在寻找一种方式,以便它们在DoCalc中执行,Update后跟DoCalc,Update后跟DoCalc,Update。
相反,我看到的是DoCalc,DoCalc,Update,Update,DoCalc,Update,即它们从不按顺序运行。
有没有办法可以在Rx中强制执行它
答案 0 :(得分:2)
我发现一方面需要执行顺序,另一方面调度到另一个线程之间存在冲突。我的建议是将Update
分为两部分:
然后您可以按顺序调用Do(Update)
,并在调度程序上调用Subscribe(Dispatch)
:
var result =
Stream()
.SubscribeOn(new EventLoopScheduler())
.Select(DoCalc)
.Do(Update)
.ObserveOn(DispatcherScheduler.Current)
.Subscribe(Dispatch);
结果序列是这样的(“更新n”之后的任何时间都可能发生“调度n”调用):
Select a Update a Select b Update b Dispatch a Dispatch b
我想另一种方法是使用ManualResetEvent
,这表明下一个DoCalc只能在更新发生后才能继续。您可以通过将ManualResetEvent.WaitOne
添加到DoCalc并将ManualResetEvent.Set
添加到更新来执行此操作:
private ManualResetEvent _wait = new ManualResetEvent(true);
private string DoCalc(string input)
{
_wait.WaitOne();
Console.WriteLine("Selected {0}", input);
_wait.Reset();
return input;
}
private void Update(string input)
{
Console.WriteLine("Update {0}", input);
_wait.Set();
}
这第二种方法“有效”,但这样的线程阻塞让我感到不安 - 它似乎与反应式编程的交叉目的有效。当然,同样地,it's best to avoid introducing state, if possible.