反应性延伸的可观察模式

时间:2015-09-04 12:54:33

标签: c# .net system.reactive

我试图理解下面的代码试图使用反应式扩展

 IObservable<string> textChangedObservable =
            Observable.FromEventPattern<TextChangedEventArgs>(searchScrip, "TextChanged")
                .Select(evt => ((TextBox) sender).Text);

 textChangedObservable.Subscribe(OnNext, OnCompleted);

private void OnNext(string s)
    {
        System.Diagnostics.Debug.Print("OnNext " + s + "\n");
    }

    private void OnCompleted()
    {
        System.Diagnostics.Debug.Print("OnCompleted " + "\n");
    }

如果我在输入框中输入SEARC,则输出看起来

  • OnNext SE
  • OnNext SEA
  • OnNext SEA
  • OnNext SEAR
  • OnNext SEAR
  • OnNext SEAR
  • OnNext SEARC
  • OnNext SEARC
  • OnNext SEARC
  • OnNext SEARC

    1. 为什么“S”没有触发OnNext?
    2. 为什么OnCompleted从未被调用?
    3. 为什么OnNext在第n个字符上调用了n-1次?

3 个答案:

答案 0 :(得分:3)

您似乎订阅了searchScrip_TextChanged处理程序中的observable。

这意味着第一次searchScrip_TextChanged被调用S已经发生之前您已连接了observable。所以当然不会开火。

但是现在S已被点击,您有一个订阅,因此当输入E时,您会获得一个SE。但是由于searchScrip_TextChanged处理程序也被调用E,你现在有两个订阅你的observable。

因此,当输入A时,您会得到两个SEA,因为您有两个可观察对象。但是再次为searchScrip_TextChanged调用了A,所以现在你有三个可观察量。

Etc等等。

事件未自动完成。您需要手动处理订阅以使它们结束。这应该是有意义的,因为这是你想要停止的普通事件处理程序所必须做的。

您应该在加载表单时创建observable,以便创建一次。

它应该是这样的:

IObservable<string> textChangedObservable =
        Observable.FromEventPattern<TextChangedEventArgs>(searchScrip, "TextChanged")
            .Select(evt => searchScrip.Text);

IDisposable subscription =
    textChangedObservable
        .Subscribe(
            s => Debug.Print("OnNext " + s + "\n"),
            s => Debug.Print("OnCompleted\n"));

答案 1 :(得分:2)

这里的问题与Rx无关。

  

1:为什么&#34; S&#34;没有触发OnNext?

因为您订阅的TextChanged事件未在第一个S上触发。

  

2:为什么OnCompleted从未被调用过?

当您将.NET事件包装为IObservable<T>时,您永远不会收到OnErrorOnCompleted次通知。 .NET事件没有错误或完成的概念。

如果有两个事件,一个用于值,一个用于完成,您可以将它们组合起来:

var values = Observable.FromEvent(...);
var completion = Observable.FromEvent(...);
var query = values.TakeUntil(completion);

现在query会产生正确的OnCompleted通知。

  

3:为什么OnNext在第n个字符上调用了n-1次?

因为您已订阅的TextChanged事件以此方式触发。正如@ Kari-Antti所指出的,这可能是使用&#34;路由属性的副作用&#34;事件

答案 2 :(得分:-1)

也许是因为你使用过RoutedPropertyChangedEventArgs?

如果使用PropertyChangedEventHandler怎么办?

%let text = abc\pqr{work};
data _null_;
   var=prxchange("s/\\/\\\\/",-1,"&text");
   var=prxchange("s/\{/\\\{/",-1,var);
   var=prxchange("s/\}/\\\}/",-1,var);
   put var;
run;