我应该总是处置观测时, ViewModel
保持自动超出范围和其他类没有提及?
一个小例子:
public class TestViewModel : ReactiveObject
{
public TestViewModel()
{
MyList = new ReactiveList<string>();
MyList.ChangeTrackingEnabled = true;
//Do I have to dispose/unsubscribe this?
MyList.ItemChanged.Subscribe(_ => ...);
//Or this?
this.WhenAnyValue(x => x.MyList).Subscribe(_ => ...);
}
ReactiveList<string> _myList;
public ReactiveList<string> MyList
{
get => _myList;
set => this.RaiseAndSetIfChanged(ref _myList, value);
}
}
从我了解的订阅是普通的.NET对象。 随着外没有参考ViewModel
类。 所以,当我TestViewModel
超出范围(即object
永远不会再使用,并用另一个替换)的GarbageCollector
应该清理所有视图模型里面的东西,所以我没有手动调用Dispose
对返回IDisposables
。
我是正确吗?
编辑
该ReactiveList
还可以持有其他.NET对象。 这个例子是不特定的不可变的字符串类型。
这是肯特Boogart(该ReactiveUI维护者之一)对此事的看法:
所以,假设......如果你使用WhenActivated
的观点,当你处理一次性的,它返回? 你必须将它存储在本地领域,使视图一次性的。 但是,那么谁的观点的处置? 你需要的平台挂钩知道什么时候适当的时候处理它 - 如果这观点是在虚拟化场景重用不是一件小事。 因此,有这一点。
而且,当你执行一个功指令是什么? 你存储关闭一次性你这样你就可以“清理”以后呢? 我会想不会,有很好的理由。 当执行完成后,所有观察员都自动退订反正。 通常,订阅到具有有限的寿命(例如,通过超时)管道不必手动地设置。 这种订阅的处置是关于作为处置有用MemoryStream
。
除了这个,我发现,特别是在虚拟机反应代码往往兼顾了很多一次性的。 存储所有这些一次性用品,并企图处置趋于混乱的代码,并迫使VM本身是一次性的,进一步的混乱问题。 逆足是要考虑,特别是对Android的另一个因素。
所以我的建议从这个一切都源于。 我发现,呼唤那些需要处理订阅在包装他们WhenActivated
是最务实的做法。
要回答这样的为您的具体情况的问题,你必须使用诊断工具来找出你的情况是什么在起作用。
一个测试与运行using
块和一个无:
class Program
{
static void Main(string[] args)
{
//warmup types
var vm = new TestViewModel();
Console.ReadLine(); //Snapshot #1
for (int i = 0; i < 1000; i++)
Model();
GC.Collect();
Console.ReadLine(); //Snapshot #2
}
private static void Model()
{
using (var vm = new TestViewModel())
{
}
}
}
无需手动配置:
设置在两个订阅:
对于1K迭代,差异是轻微的,GC是做自己的工作。 区别只是WeakReference
类型。
最终,因为格伦·沃森说,你必须按个别情况决定。 它采用定期调度观测是手动配置一个很好的候选人。
ReactiveUI准则时处置订阅
你永远不应该依赖垃圾收集干净地处理你的对象。
终结有一个最大的执行时间,并可以以任何顺序执行, Dispose
会,如果处置模式是正确实施甚至没有被调用。
Dispose
应清理托管资源和终结应清理非托管资源,以避免内存泄漏。 该Disposing(bool)
模式将调用上都明确的Dispose
,只有在垃圾收集非托管。
明确的Dispose
也可以让你更早清理,而不是等到GC收集。
具体用于订阅,事件处理等不清除的引用可能意味着,当GC不会收集,引用仍然存在,在这种情况下,物体将不会在所有收集到的。
如果你知道有根没有路,你可能不严格必须明确处理,但往往在这种情况下,有人走来后,不慎在图形保持一个引用一个对象,你知道它之前,整个图可以从不收集。