在WPF应用程序中,我使用Observable.Throttle()
来限制处理来自用户界面的某些事件的频率。
这是与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));
}
}
这通常很有效,可以解决我们以前的种族问题。但是,在某些时候,即使事件频率较低,这也会锁定subject.OnNext()
。此时在Visual Studio中暂停显示以下相关调用堆栈:
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)
我认为/希望根本原因是我非常天真/没有经验的使用Rx。我尝试同步这个主题,我记得在不同的地方帮助我解决了一个问题,但这并没有改变这里的行为。我还尝试了SubscribeOn()
/ ObserveOn()
,但没有真正的计划或运气。
我使用的主题是错的吗?我应该使用不同的主题类型吗?我应该使用一个主题吗? (由于现实代码的复杂性,通过Rx直接附加到视图中的事件并合并流似乎不可行。)
感谢您的任何指示!