locked
Observable.FromEvent throws in v1.0.10425 RRS feed

  • Question

  • I'm having trouble using the new Observable.FromEvent with typical WPF events - here's my code:

     

    Observable.FromEvent<SizeChangedEventHandler, SizeChangedEventArgs>(
     x => SizeChanged += x, x => SizeChanged -= x)
     .Select(_ => Unit.Value);
    
    

     

    And here's the result:

     

    System.ArgumentException: Error binding to target method.
    
     at System.Delegate.CreateDelegate(Type type, Object firstArgument, MethodInfo method, Boolean throwOnBindFailure)
     at System.Delegate.CreateDelegate(Type type, Object firstArgument, MethodInfo method)
     at System.Reactive.Linq.Observable.<>c__DisplayClass2c0`2.<FromEvent>b__2be(IObserver`1 observer)
     at System.Reactive.AnonymousObservable`1.Subscribe(IObserver`1 observer)
     at System.ObservableExtensions.Subscribe[TSource](IObservable`1 source, Action`1 onNext, Action`1 onError, Action onCompleted)
     at System.Reactive.Linq.Observable.<>c__DisplayClass413`2.<Select>b__411(IObserver`1 observer)
     at System.Reactive.AnonymousObservable`1.Subscribe(IObserver`1 observer)
     at System.ObservableExtensions.Subscribe[TSource](IObservable`1 source, Action`1 onNext, Action`1 onError, Action onCompleted)
     at System.Reactive.Linq.Observable.<>c__DisplayClass302`1.<>c__DisplayClass304.<Merge>b__2fc(IObservable`1 innerSource)
     at System.Reactive.AnonymousObserver`1.Next(T value)
     at System.Reactive.AbstractObserver`1.OnNext(T value)
     at System.Reactive.AnonymousObservable`1.AutoDetachObserver.Next(T value)
     at System.Reactive.AbstractObserver`1.OnNext(T value)
     at System.Reactive.Linq.Observable.<>c__DisplayClass29e`1.<Subscribe>b__29d(Action self)
     at System.Reactive.Concurrency.Scheduler.<Schedule>b__0(Action`1 _action, Action`1 self)
     at System.Reactive.Concurrency.Scheduler.<>c__DisplayClassb`1.<InvokeRec1>b__8(TState state1)
     at System.Reactive.Concurrency.Scheduler.InvokeRec1[TState](IScheduler scheduler, Pair`2 pair)
     at System.Reactive.Concurrency.ImmediateScheduler.Schedule[TState](TState state, Func`3 action)
     at System.Reactive.Concurrency.Scheduler.Schedule[TState](IScheduler scheduler, TState state, Action`2 action)
     at System.Reactive.Concurrency.Scheduler.Schedule(IScheduler scheduler, Action`1 action)
     at System.Reactive.Linq.Observable.Subscribe[TSource](IEnumerable`1 source, IObserver`1 observer, IScheduler scheduler)
     at System.Reactive.Linq.Observable.<>c__DisplayClass2d7`1.<ToObservable>b__2d6(IObserver`1 observer)
     at System.Reactive.AnonymousObservable`1.Subscribe(IObserver`1 observer)
     at System.ObservableExtensions.Subscribe[TSource](IObservable`1 source, Action`1 onNext, Action`1 onError, Action onCompleted)
     at System.Reactive.Linq.Observable.<>c__DisplayClass302`1.<Merge>b__2fb(IObserver`1 observer)
     at System.Reactive.AnonymousObservable`1.Subscribe(IObserver`1 observer)
     at System.ObservableExtensions.Subscribe[TSource](IObservable`1 source, Action`1 onNext, Action`1 onError, Action onCompleted)
     at System.Reactive.Linq.Observable.<>c__DisplayClass413`2.<Select>b__411(IObserver`1 observer)
     at System.Reactive.AnonymousObservable`1.<>c__DisplayClass1.<Subscribe>b__0()
     at System.Reactive.Concurrency.Scheduler.Invoke(IScheduler scheduler, Action action)
     at System.Reactive.Concurrency.ScheduledItem`2.InvokeCore()
     at System.Reactive.Concurrency.ScheduledItem`1.Invoke()
     at System.Reactive.Concurrency.CurrentThreadScheduler.Trampoline.Run()
     at System.Reactive.Concurrency.CurrentThreadScheduler.Schedule[TState](TState state, TimeSpan dueTime, Func`3 action)
     at System.Reactive.Concurrency.CurrentThreadScheduler.Schedule[TState](TState state, Func`3 action)
     at System.Reactive.Concurrency.Scheduler.Schedule(IScheduler scheduler, Action action)
     at System.Reactive.AnonymousObservable`1.Subscribe(IObserver`1 observer)
     at System.ObservableExtensions.Subscribe[TSource](IObservable`1 source, Action`1 onNext, Action`1 onError, Action onCompleted)
     at System.ObservableExtensions.Subscribe[TSource](IObservable`1 source, Action`1 onNext)
     at ReactiveUI.Sample.Views.BlockTimerWindow..ctor(BlockItem Model) in C:\Users\Administrator\Dropbox\ReactiveUI_External\ReactiveUI.Sample\ReactiveUI.Sample\Views\BlockTimerWindow.xaml.cs:line 44
    

     

    Any clues?

     


    Tuesday, May 3, 2011 5:13 PM

Answers

  • Use FromEvent for events structurally don't look like a .NET event pattern (i.e. not based on sender, event args), and use FromEventPattern for the pattern-based ones. The sample code show for FromEvent above violates this distinction and uses an EventHandler inside (which indicates the use of the pattern). Does this make sense?
    using (Microsoft.Sql.Cloud.DataProgrammability.Rx) { Signature.Emit("Bart De Smet"); }
    Friday, May 20, 2011 6:35 PM

All replies

  • I duplicated the issue, but then changed it to use Observable.FromEventPattern instead, and it works.
    Tuesday, May 3, 2011 7:51 PM
  • The code for FromEvent should be something like this: 

     

    public static IObservable<TEventArgs> FromEvent<TDelegate, TEventArgs>(Action<TDelegate> addHandler, Action<TDelegate> removeHandler) where TEventArgs : EventArgs
    {
     if (addHandler == null)
     {
      throw new ArgumentNullException("addHandler");
     }
     if (removeHandler == null)
     {
      throw new ArgumentNullException("removeHandler");
     }
     return Observable.Create<TEventArgs>(delegate(IObserver<TEventArgs> observer)
     {
      EventHandler<TEventArgs> firstArgument = new EventHandler<TEventArgs>((_, args) => observer.OnNext(args));
      TDelegate d = (TDelegate)(object)Delegate.CreateDelegate(typeof(TDelegate), firstArgument, typeof(EventHandler<TEventArgs>).GetMethod("Invoke"));
      addHandler(d);
      return Disposable.Create(delegate
      {
       removeHandler(d);
      });
     });
    }
    

     


    Wednesday, May 4, 2011 7:03 PM
  • Another thread http://social.msdn.microsoft.com/Forums/en-US/rx/thread/4f6c28ce-4ae9-470b-99bc-182e1afa712e mentions that FromEvent doesn't work with WPF in the latest drop. User FromEventPattern instead.

     

     


    Dan Sullivan
    Monday, May 9, 2011 1:10 AM
  • Use FromEvent for events structurally don't look like a .NET event pattern (i.e. not based on sender, event args), and use FromEventPattern for the pattern-based ones. The sample code show for FromEvent above violates this distinction and uses an EventHandler inside (which indicates the use of the pattern). Does this make sense?
    using (Microsoft.Sql.Cloud.DataProgrammability.Rx) { Signature.Emit("Bart De Smet"); }
    Friday, May 20, 2011 6:35 PM