我怎么能处理 - 或与Rx?

时间:2012-04-28 19:10:51

标签: system.reactive

我需要使用Reactive-Extensions来处理任何一种情况。

我收到了2件事(A或B)。当事件A进入后跟事件B在2秒内我想生成C.如果A后面没有B,那么我想生成一个D.

有没有办法用Rx表达呢?

由于

3 个答案:

答案 0 :(得分:3)

这是你可以做到的一种方式:

Observable.Merge(eventA, eventB)
    .Timestamp()
    .Buffer(2 /*items*/,1 /*at a time*/)
    .SelectMany(x => {
        if (x[1].Timestamp - x[0].Timestamp < TimeSpan.FromSeconds(2.0) &&
            x[0].Value.EventType == "A" && x[1].Value.EventType == "B") {
            return Observable.Return(new C());
        }

        if (x[0].Value.EventType == "A" && x[1].Value.EventType != "B") {
            return Observable.Return(new D());
        }

        return Observable.Empty<AnEvent>();
    });

答案 1 :(得分:0)

SelectMany以及返回备用observable的Timeout重载应该能够执行您描述的操作。

Dim obsA = Observable.Interval(TimeSpan.FromSeconds(1)) 'whatever your source is
Dim obsB = Observable.Interval(TimeSpan.FromSeconds(0.5)) 'whatever your source is
'replace with your actual C/D generation functions
Dim final = From a In obsA
            From b In obsB.Select(Function(i) "C" & a.ToString()) _
                          .Timeout(TimeSpan.FromSeconds(2),
                                   Observable.Return("D" & a.ToString())) _
                          .Take(1)
            Select b

答案 2 :(得分:0)

使用内置的Amb运算符,这似乎相当容易。

首先定义obsC&amp; obsD喜欢这样:

var obsC = Observable.Return('C');

var obsD = Observable.Delay(
    Observable.Return('D'),
    TimeSpan.FromSeconds(2.0));

现在我想要一个“B”然后“C”可观察。在最新的“B”之后我只想要一个“C”。如果两个“B”出现我只想要最新的一个。这是:

var obsBC =
    obsB
        .Select(_ => obsC)
        .Switch()
        .Take(1);

现在为最终查询将所有内容与Amb运算符结合在一起:

var query =
    from a in obsA
    from cd in Observable.Amb(obsBC, obsD)
    select cd;

我的测试显示此查询有效。但与所有这些事情一样,如果两个“A”在“B”之前进入,则不清楚该怎么办。我可以得到“D”/“C”或“C”/“C”或只是“D”或“C”吗?根据所需的行为,我的查询可能需要更改。