C# 从事件中可观察到

C# 从事件中可观察到,c#,system.reactive,C#,System.reactive,我是Rx的新手,在查看一些样本时,遇到了以下问题: Observable.FromEventPattern<RoutedEventHandler, RoutedEventArgs>( h => new RoutedEventHandler(h), h => Loaded += h, h => Loaded -= h) .Select(_ => true)

我是Rx的新手,在查看一些样本时,遇到了以下问题:

    Observable.FromEventPattern<RoutedEventHandler, RoutedEventArgs>(
            h => new RoutedEventHandler(h),
            h => Loaded += h,
            h => Loaded -= h)
            .Select(_ => true)
            .StartWith(IsLoaded)
            .Where(l => l)
            .Take(1)
            .Subscribe(_ => Console.WriteLine("loaded");
Observable.FromEventPattern(
h=>新的路由EventHandler(h),
h=>Loaded+=h,
h=>Loaded-=h)
.选择(=>true)
.StartWith(已加载)
.其中(l=>l)
.采取(1)
.Subscribe(=>Console.WriteLine(“已加载”);
我试图解构这句话,找出它在做什么,但我并不是100%清楚

我理解FromEventPattern是如何将加载的事件转化为一个可观察的序列的。现在,当IsLoaded为真时(IsLoaded)将触发选择是否只是从RoutedEventTargets获取其信息

现在,我不知道为什么会有StartsWithStartsWith会将一个值序列预先添加到一个可观察序列中。那么它只是将IsLoaded的值添加到列表的开头吗?在Select发生后,它不会已经存在了吗

.Where未应用任何类型的过滤器,因此.Take将只获取序列的第一个值(在本例中不再使用该值)。然后它订阅,并且仅在加载控件时写入控制台

这一分析基本正确吗


还有,关于调试这些东西的任何提示(意思是,在链的不同阶段序列是什么样子的)?我只需附加调试器就可以获得信息,但我想知道是否还有其他常用的技巧/提示。

大多数可观察运算符的工作方式与同名可枚举运算符的工作方式相同。如果您有使用这些运算符的经验,这里将非常有用

为了解决这个问题,让我们先用一个整数数组,而不是可观察的数组

int[] data = {1, 2, 3, 4};
这会将表达式更改为

var results = data.Select(_ => true) 
                  .StartWith(IsLoaded)
                  .Where(l => l)
                  .Take(1);
foreach (var r in results)
{
    Console.WriteLine("loaded");
}
如果在表达式的每个阶段创建一个数组,则会得到:

Select - {true, true, true, true}
StartWith - {value of IsLoaded, true, true, true, true}
Where - (if IsLoaded is true)  {true, true, true, true, true}
        (if IsLoaded is false) {true, true, true, true}
Take - {true}
对于IEnumerables,这样做没有多大意义,因为您总是会得到一个为真的值(除非源数组为空且IsLoaded为假)

将其与IObservable一起使用是为了在加载对象时生成一个信号

  • 如果订阅时已加载对象,则
    StartWith
    is将提供信号
  • 但是,如果对象未加载,
    IsLoaded
    将为false,
    Where
    将过滤掉它,当事件触发时,它将触发通知。
    • Select
      将忽略事件产生的实际数据,只传递一个true,该true将通过
      Where
      过滤器继续执行
  • Take
    仅用于触发通知一次,无论它来自
    StartWith
    ,因为加载完成时对象已加载,或事件(通过
    Select
    )已加载

如果您是Rx新手,并且需要了解每个运营商的工作,您可以尝试一下-它使用旧版本的Rx,但您可能可以在进入v2之前从v1中学习。它允许您在流上可视化和尝试组合器,并将结果作为示例显示给您

下面是
Zip
操作符的表示

很容易看出,它将来自任一流的两个值配对

调试序列的一种简单方法是在两者之间使用
Do
操作符,如下所示:

    static IObservable<T> Log<T>(this IObservable<T> stream, string name)
    {
        return stream.Materialize()
                     .Do(n => Console.WriteLine("{0} - {1}",name, n))
                     .Dematerialize();
    }
您可以看到每个值沿管道向下传播:

Timer - OnNext(0)
Where - OnNext(0)
Timer - OnNext(1)
Timer - OnNext(2)
Where - OnNext(2)
Timer - OnNext(3)
Sample - OnNext(2)
Take - OnNext(2)
Take - OnCompleted()

我对RX也是新手。根据使用情况,我怀疑<>代码> 不是必需的。对于进程中的任何步骤,您可以手动注入DO方法并将结果输出到控制台(C++中,这是已知的PrtTf调试)。。您可能还想试用该工具,以直观地查看运行时的情况。@neontapri,如果订阅时IsLoaded属性的值为false,则where将删除false值,就像在StartWith操作符中一样。请注意。所讨论的代码只是在对象(控件?)运行时生成一个单值序列若在订阅时已加载,则立即推送一个值,否则在加载时将推送该值。
Timer - OnNext(0)
Where - OnNext(0)
Timer - OnNext(1)
Timer - OnNext(2)
Where - OnNext(2)
Timer - OnNext(3)
Sample - OnNext(2)
Take - OnNext(2)
Take - OnCompleted()