我无法获得Observable.FromEvent(...)。ToEnumerable()工作

时间:2010-12-03 18:19:24

标签: .net system.reactive

当我尝试从本机.NET事件创建的IObservable获取IEnumerable时,IEnumerable会在查询第一个元素时阻塞。我做错了什么?

我已经建立了一个小完整的例子。第一个测试方法阻塞,尽管事件被另一个IObservable正确推送。第二种测试方法适用于普通数组,不会阻塞。

谢谢!

using System;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace TestGTI.Reactive
{

    class ItHappenedEventArgs : EventArgs
    {
    }

    class A
    {
        public event EventHandler<ItHappenedEventArgs> ItHappened;

        public void RaiseItHappened(ItHappenedEventArgs e)
        {
            if (ItHappened != null)
            {
                ItHappened(this, e);
            }
        }
    }

    [TestClass]
    public class ReactiveTest
    {
        [TestMethod]
        public void EnumerateEventTest()
        {
            var a = new A();

            ItHappenedEventArgs pushed = null;
            Observable.FromEvent<ItHappenedEventArgs>(a, "ItHappened").Subscribe(e =>
                {
                    pushed = e.EventArgs;
                });

            var itHappenedEnum = Observable.FromEvent<ItHappenedEventArgs>(a, "ItHappened").ToEnumerable();

            var itHappenedEventArgs = new ItHappenedEventArgs();
            a.RaiseItHappened(itHappenedEventArgs);

            Assert.AreSame(itHappenedEventArgs, pushed);

            // blocks!!!
            Assert.AreSame(itHappenedEventArgs, itHappenedEnum.First());        
        }

        [TestMethod]
        public void ObservableToEnumerableTest()
        {
            var array = new int[] { 1, 2, 3 };
            var enumerable = array.ToObservable().ToEnumerable();

            // works
            Assert.AreEqual(1, enumerable.First());
        }
    }
}

2 个答案:

答案 0 :(得分:3)

枚举时IEnumerable是懒惰的,ToEnumerable在您开始枚举之前不会订阅源。

在您的示例中,您是在之后第一次引发事件时调用First() ,因此您订阅源并且没有发出任何值,因此阻塞。基本上在你聆听的时候,价值已经过去了。

如果您想记住该值,可以使用PruneReplay(请记住连接到返回的IConnectableObservable以开始收听)。然后,您可以使用ToEnumerable并发出值。

答案 1 :(得分:0)

理查德就在这里,但我也从概念视图中添加它 - IEnumerable通常(在实践中,但不是必须的)是有限大小列表的抽象。 FromEvent是一个永不终止的IObservable - 创建一个无限大小的列表是否有意义?我无法用很多实际的东西......