15

いくつかの条件が変化したときにシグナリングする2つのストリームがあります。すべての条件が変わっtrueたときに起動するObservableが必要です。それらのいずれかが回ったとき。いくつかの条件があり、別の条件が変更された場合、イベントを発生させる必要はありません。truefalsefalsefalsefalse

これが私がそれをしている方法です:

// Introducing current states
private bool cond1 = false;
private bool cond2 = false;

void MyHandlingMethod(IObservable<bool> c1, IObservable<bool> c2)
{
    c1.Subscribe(b => _state1 = b);
    c2.Subscribe(b => _state2 = b);

    var c3 = c1.Merge(c2).Select(_ => _cond1 && _cond2);

    c3.Subscribe(b => /* some action goes here /*);
    // ...
}

それが私の問題を解決する正しい方法であるかどうか、そして落とし穴があるかどうかを知りたいです。たとえば、rxの非同期性により、c3サブスクリプションはc1とc2の前に起動します。

4

3 に答える 3

18

状態を維持する必要はありません。

c3 = c1.CombineLatest(c2, (a, b) => a && b).DistinctUntilChanged()
于 2013-03-13T14:35:41.527 に答える
2

正直なところ、私はおそらくこのCombineLatestアプローチを採用しますが、Rxフレームワークのやや手つかずの部分に触れるために...

完璧にフィットするわけではありませんが、//パターンを使用Observable.WhenできますObservable.AndObservable.Then

var firstStream = new Subject<bool>();
var secondStream = new Subject<bool>();
var thirdStream = new Subject<bool>();
var fourthStream = new Subject<bool>();

var query = Observable.When(firstStream
        .And(secondStream)
        .And(thirdStream)
        .And(fourthStream)
        .Then((v1,v2,v3,v4) => v1 & v2 & v3 & v4));

using(query.Subscribe(Console.WriteLine))
{
    firstStream.OnNext(true);
    secondStream.OnNext(true);
    thirdStream.OnNext(true);
    // output stream will fire after this statement
    fourthStream.OnNext(true);
    Console.ReadLine();
}

このアプローチの利点の1つは、すべてのストリームに句に従って結合されたデータがある場合にのみ出力イベントを作成することです。これは、Thenかなり適切に読み取られます。とはいえ、ユースケースには重大な失敗が1つあります。出力ストリームをトリガーするには、各着信ストリームにデータが必要です。

using(query.Subscribe(Console.WriteLine))
{
    firstStream.OnNext(true);
    secondStream.OnNext(true);
    thirdStream.OnNext(true);
    // output stream will fire after this statement
    fourthStream.OnNext(true);

    // this WON'T raise false on the output!
    firstStream.OnNext(false);
    secondStream.OnNext(false);
    thirdStream.OnNext(false);
    // output stream will fire false after this statement
    fourthStream.OnNext(false);
    Console.ReadLine();
}
于 2013-03-13T15:32:58.530 に答える
0

JerKimballのように、Joins(現在はWhen)の使用を提案しました。

IObservable<bool> cond1 = new [] { false, true, true, false, false }.ToObservable();
IObservable<bool> cond2 = new [] { true, true, false, false, true }.ToObservable();
Func<bool, bool> isFalse = (x) => x == false;
Func<bool, bool> isTrue = (x) => x == true;
var trueC1s = cond1.Where(isTrue);
var falseC1s = cond1.Where(isFalse);
var trueC2s = cond2.Where(isTrue);
var falseC2s = cond2.Where(isFalse);
var trues = trueC1s.And(trueC2s).Then((_, __) => true);
var falses = trueC1s.And(falseC2s).Then((_, __) => false);
var falses2 = falseC1s.And(trueC2s).Then((_, __) => false);
var falses3 = falseC1s.And(falseC2s).Then((_, __) => false);
Observable.When(trues, falses, falses2, falses3).Dump();

ただし、Observableが多い場合は、少し面倒になります。

于 2013-03-13T15:50:31.837 に答える