In a WPF application, I am using Observable.Throttle() to limit the frequency of handling certain events coming in from the user interface.
This is the minimal simplified code as it pertains to the usage of Rx:
using System.Reactive.Linq;
using System.Reactive.Subjects;
public class UIEvent
{
public UIEvent(string name)
{
this.Name = name;
}
public string Name { get; }
}
public class ViewModel
{
private ISubject<UIEvent> subject = new Subject<UIEvent>();
// IEventAggregator is from Caliburn.Micro, but that should not be relevant here.
public ViewModel(IEventAggregator eventAggregator)
{
this.subject
.Throttle(TimeSpan.FromMilliseconds(500))
.Subscribe(eventAggregator.Publish);
}
// This is called from several places in the associated view
public RaiseUiEvent(string name)
{
this.subject.OnNext(new UIEvent(name));
}
}
This generally works well and solves the race issue we had before. However, at some point, and even with a low frequency of events coming in, this will lock up in subject.OnNext(). Pausing in Visual Studio at that point shows the following relevant call stack:
WindowsBase.dll!System.Windows.Threading.DispatcherSynchronizationContext.Wait(System.IntPtr[] waitHandles, bool waitAll, int millisecondsTimeout)
[Native to Managed Transition] Annotated Frame
[Managed to Native Transition] Annotated Frame
System.Reactive.Linq.dll!System.Reactive.Linq.ObservableImpl.Throttle<UIEVent>._.OnNext(UIEvent value)
ViewModel.RaiseUiEvent(string name)
I assume/hope the root cause is my very naive/inexperienced use of Rx. I tried synchronizing the subject, which I remember helped me with an issue in a different place, but that didn't change anything about the behavior here. I also experimented with SubscribeOn()/ObserveOn(), but with no real plan or luck.
Am I using the subject wrong? Should I be using a different subject type? Should I be using a subject at all? (Directly attaching to the events in the view via Rx and merging the streams does not seem feasible because of the complexity of the real-world code.)
Thanks for any pointers!