Я не могу заставить Observable.FromEvent (...). ToEnumerable () работать - PullRequest
1 голос
/ 03 декабря 2010

Когда я пытаюсь получить IEnumerable из IObservable, который был создан из собственного события .NET, 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 ]

3 голосов
/ 04 декабря 2010

IEnumerable ленив, когда дело доходит до перечисления, и ToEnumerable не подписывается на источник, пока вы не начнете перечислять.

В вашем примере вы звоните First() после вы впервые вызвали событие, поэтому вы подписываетесь на источник, и значение не выдается, следовательно, блокировка.В основном к тому времени, когда вы слушаете, значение уже пришло и ушло.

Если вы хотите запомнить значение, вы можете использовать Prune или Replay (не забудьте подключиться к возвращенному IConnectableObservableначать слушать).Затем вы можете использовать ToEnumerable, и значение будет отправлено.

0 голосов
/ 27 января 2011

Ричард здесь, но я бы также добавил это из концептуального представления - IEnumerable обычно (на практике, но не обязательно) является абстракцией для списка конечного размера.FromEvent - это IObservable, который никогда не завершается - имеет ли смысл создавать список бесконечного размера?Там не так много практических вещей, которые я мог бы сделать с этим ...

...