我从博客中查看了 ReactiveUi 的示例,我想知道 ReactiveUI 在下面是否有某种订阅管理工具,或者这些示例是否忽略了它们可能会泄露订阅的事实?
每当我在 ReactiveUi 中调用导致 的方法时IDisposable
,我是否需要保留该引用并自己跟踪它?这是否也意味着我的 ViewModel 需要是一次性的,这似乎很困难,因为我们真的不知道 WPF 中连接的“视图”何时消失(即我的 ViewModel 是否反映了数据网格中的项目)所以似乎没有合适的调用处置的地方。
我从博客中查看了 ReactiveUi 的示例,我想知道 ReactiveUI 在下面是否有某种订阅管理工具,或者这些示例是否忽略了它们可能会泄露订阅的事实?
每当我在 ReactiveUi 中调用导致 的方法时IDisposable
,我是否需要保留该引用并自己跟踪它?这是否也意味着我的 ViewModel 需要是一次性的,这似乎很困难,因为我们真的不知道 WPF 中连接的“视图”何时消失(即我的 ViewModel 是否反映了数据网格中的项目)所以似乎没有合适的调用处置的地方。
您还必须记住,由 Rx 和 ReactiveUI 返回的 IDisposables 与非托管内存无关——它们只是简单的 .NET 对象,仍由垃圾收集器引用。
您在 ReactiveObjects 的构造函数中进行的大多数订阅都将与宿主对象的生命周期相关联 - 因此,当它超出范围并受 GC 影响时,所有订阅也会如此,CLR 将检测循环引用并只是核爆一切。
正如 Enigmativity 所提到的,一个棘手的问题是当您使用 FromEventPattern 将 Subscription(可能还有 ViewModel)的生命周期与 WPF 对象的生命周期联系起来时。但是,我认为如果您经常在 ReactiveUI 中使用 FromEventPattern,那么您肯定是在做错事™。
RxUI 都是关于 ViewModels 的,而 ViewModels 都是关于命令和属性的(以及连接属性如何相互关联),因此您可以将用户体验的行为与其视觉效果分开测试。
如果您需要提前IDisposable
取消订阅observable,您只需要保留对订阅返回的引用。当 Observable 被or消息终止时,它们自然会调用。Dispose
OnCompleted
OnError
但是,当您拥有无限的可观察订阅(即FromEventPattern
)时,您确实需要保留引用,但这与在关闭表单/视图之前需要删除事件处理程序完全相同。
为了安全起见,我将从现在开始使用这种模式。我可能会修改为通过扩展方法工作,但原则是合理的。为确保您不会泄露您想要删除的订阅
class Mesh2D{
public Mesh2D()
{
DisposeOnUnload(CreateBindings());
}
// Register all disposables for disposal on
// UIElement.Unload event. This should be
// moved to an extension method.
void DisposeOnUnload(IEnumerable<IDisposable> disposables)
{
var d = new CompositeDisposable(disposables);
var d2 = this.UnloadedObserver()
.Subscribe(e => d.Dispose());
var d3 = this.Dispatcher.ShutdownStartedObserver()
.Subscribe(e => d.Dispose());
d.Add(d2);
d.Add(d3);
}
// Where your bindings are simply yielded and
// they are removed on Unload magically
IEnumerable<IDisposable> CreateBindings()
{
// When the size changes we need to update all the transforms on
// the markers to reposition them.
yield return this.SizeChangedObserver()
.Throttle(TimeSpan.FromMilliseconds(20), RxApp.DeferredScheduler)
.Subscribe(eventArgs => this.ResetImageSource());
// If the points change or the viewport changes
yield return this.WhenAny(t => t.Mesh, t => t.Viewport, (x, t) => x.Value)
.Throttle(TimeSpan.FromMilliseconds(20), RxApp.DeferredScheduler)
.Subscribe(t => this.UpdateMeshChanged());
}
}
请注意,我使用自动生成的扩展方法包装 RX FromEventPattern,因此我免费获得 SizeChangedObserver() 和 UnloadedObserver(),而不是难记的 FromEventPattern 格式。
包装代码是这样生成的
public static IObservable<EventPattern<RoutedEventArgs>> UnloadedObserver(this FrameworkElement This){
return Observable.FromEventPattern<RoutedEventHandler, RoutedEventArgs>(h => This.Unloaded += h, h => This.Unloaded -= h);
}
上述模式也可能用于解除 IDisposable 视图模型的绑定。