简体   繁体   English

反应性扩展的可观察模式

[英]Observable pattern on reactive extension

I am trying to understand the below code trying to use reactive extensions 我试图理解下面的代码尝试使用反应式扩展

 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");
    }

If I enter SEARC in the input box, the output looks 如果我在输入框中输入SEARC,输出看起来

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

    1. Why is "S" not triggering an OnNext? 为什么“ S”不触发OnNext?
    2. Why is OnCompleted never called? 为什么从不调用OnCompleted?
    3. Why is the OnNext called n-1 time on the nth character? 为什么OnNext在第n个字符上称为n-1次?

It appears that you are subscribing to the observable in your searchScrip_TextChanged handler. 您似乎在searchScrip_TextChanged处理程序中订阅了observable。

This means that the first time that searchScrip_TextChanged gets called the S has already happened before you've wired up the observable. 这意味着在连接可观察对象之前 ,第一次发生searchScrip_TextChanged被称为S情况已经发生。 So of course it doesn't fire. 因此,它当然不会触发。

But now that the S is hit you have one subscription so when the E is typed you get a single SE . 但是,既然S命中了,您就有一个订阅,所以当键入E时,您将得到一个SE But since the searchScrip_TextChanged handler gets called for the E too you now have two subscriptions to your observable. 但是,由于searchScrip_TextChanged处理函数也被调用为E您现在对可观察对象也有两个订阅。

So when the A is typed you get two SEA because you have two observables. 因此,当键入A时,您将获得两个SEA因为您有两个可观察值。 But again the searchScrip_TextChanged is called for the A so now you have three observables. 但是,再次为A调用了searchScrip_TextChanged ,因此现在您有了三个可观察到的对象。

Etc, etc, etc. 等等等等

Events don't complete automatically. 活动不会自动完成。 You need to manually dispose of the subscriptions to have them end. 您需要手动处理订阅以使订阅结束。 This should make sense because that's what you have to do with normal event handlers that you want to stop. 这应该是有道理的,因为这就是您要停止的常规事件处理程序所要做的。

You should create your observable when your form is loaded so that it is created once. 加载表单时,应该创建可观察对象,以便创建一次。

It should look like this: 它看起来应该像这样:

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"));

The problem here really has nothing to do with Rx. 这里的问题确实与Rx无关。

1: Why is "S" not triggering an OnNext? 1:为什么“ S”不触发OnNext?

Because the TextChanged event you have subscribed to did not fire on the first S. 因为您订阅的TextChanged事件没有在第一个S上触发。

2: Why is OnCompleted never called? 2:为何从未调用OnCompleted?

When you wrap a .NET event as an IObservable<T> , you never get OnError or OnCompleted notifications. 将.NET事件包装为IObservable<T> ,永远不会收到OnErrorOnCompleted通知。 There is no concept of error or completion with a .NET event. .NET事件没有错误或完成的概念。

If there are two events, one for values and one for completion, you can combine them like so: 如果有两个事件,一个用于值,一个用于完成,则可以将它们组合如下:

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

Now query will yield a proper OnCompleted notification. 现在query将产生适当的OnCompleted通知。

3: Why is the OnNext called n-1 time on the nth character? 3:为什么OnNext在第n个字符上称为n-1次?

Because the TextChanged event you have subscribed to fired this way. 因为您订阅的TextChanged事件以这种方式触发。 As was pointed out by @Kari-Antti, this may be a side effect of using a "routed property" event. 正如@ Kari-Antti指出的那样,这可能是使用“路由属性”事件的副作用。

Maybe because you have used RoutedPropertyChangedEventArgs? 也许是因为您使用过RoutedPropertyChangedEventArgs?

What about if you use PropertyChangedEventHandler? 如果使用PropertyChangedEventHandler怎么办?

Observable.FromEventPattern<PropertyChangedEventHandler, PropertyChangedEventArgs>(
                h => yourModel.propertyChanged += h,
                h => yourModel.propertyChanged -= h)
            .Where(x => x.EventArgs.PropertyName = "your_property_name");
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM