【问题标题】:Observable pattern on reactive extension反应式扩展的可观察模式
【发布时间】:2015-09-04 12:54:33
【问题描述】:

我正在尝试理解下面尝试使用响应式扩展的代码

 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 东南亚
  • OnNext 东南亚
  • OnNext SEAR
  • OnNext SEAR
  • OnNext SEAR
  • OnNext SEARC
  • OnNext SEARC
  • OnNext SEARC
  • OnNext SEARC

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

【问题讨论】:

  • 这不是一个简单的问题,因为XamTextEditor 类并非轻松可用。我怀疑这可能与它的RoutedPropertyChanged 的实现有关
  • 其实你需要告诉我们searchScripsender是什么XAML元素。
  • 将代码示例更改为使用 wpf 文本框以保持简单。但是行为仍然与问题中的相同

标签: c# .net system.reactive


【解决方案1】:

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

这意味着searchScrip_TextChanged 第一次被称为S 已经发生您连接可观察对象之前。所以它当然不会触发。

但是现在S 被击中,您有一个订阅,所以当输入E 时,您会得到一个SE。但是由于 searchScrip_TextChanged 处理程序也被调用为 E 您现在有两个订阅您的 observable。

因此,当输入 A 时,您会得到两个 SEA,因为您有两个 observables。但是 searchScrip_TextChanged 再次被调用为 A 所以现在你有三个 observables。

等等等等等等。

事件不会自动完成。您需要手动处理订阅以结束它们。这应该是有道理的,因为这就是您要停止的正常事件处理程序所要做的事情。

您应该在加载表单时创建您的 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"));

【讨论】:

    【解决方案2】:

    这里的问题真的和 Rx 无关。

    1:为什么“S”没有触发 OnNext?

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

    2:为什么永远不会调用 OnCompleted?

    当您将 .NET 事件包装为 IObservable&lt;T&gt; 时,您永远不会收到 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 所指出的,这可能是使用“路由属性”事件的副作用。

    【讨论】:

    • 1.我的 searchScript 的 XAML 是 并且当我放置一个断点时,它确实会在实现“private void searchScrip_TextChanged(object sender, RoutedPropertyChangedEventArgs e)"
    • @asb 除了我已经说过的内容之外,我不知道如何为您提供帮助。 observable 的发射与底层事件没有什么不同。这是一个非常简单的机制。所以你所说的,可观察的和事件的工作方式不同,与我所知道的事实相矛盾。
    • @TimothyShields - 他反复订阅 observable - 这就是为什么 OnNext 被称为 n - 1 次。
    • @TimothyShields - 当输入 S 时,observable 尚未被订阅。
    • @Enigmativity 我错过了它们发生 0,1,2,... 次的事实。
    【解决方案3】:

    可能是因为您使用了 RoutedPropertyChangedEventArgs?

    如果你使用 PropertyChangedEventHandler 呢?

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-02-12
      相关资源
      最近更新 更多