我要始终处置可观的订阅?(Should I always dispose subscriptions

2019-10-28 12:23发布

我应该总是处置观测时, 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对象。 这个例子是不特定的不可变的字符串类型。

Answer 1:

这是肯特Boogart(该ReactiveUI维护者之一)对此事的看法:

所以,假设......如果你使用WhenActivated的观点,当你处理一次性的,它返回? 你必须将它存储在本地领域,使视图一次性的。 但是,那么谁的观点的处置? 你需要的平台挂钩知道什么时候适当的时候处理它 - 如果这观点是在虚拟化场景重用不是一件小事。 因此,有这一点。

而且,当你执行一个功指令是什么? 你存储关闭一次性你这样你就可以“清理”以后呢? 我会想不会,有很好的理由。 当执行完成后,所有观察员都自动退订反正。 通常,订阅到具有有限的寿命(例如,通过超时)管道不必手动地设置。 这种订阅的处置是关于作为处置有用MemoryStream

除了这个,我发现,特别是在虚拟机反应代码往往兼顾了很多一次性的。 存储所有这些一次性用品,并企图处置趋于混乱的代码,并迫使VM本身是一次性的,进一步的混乱问题。 逆足是要考虑,特别是对Android的另一个因素。

所以我的建议从这个一切都源于。 我发现,呼唤那些需要处理订阅在包装他们WhenActivated是最务实的做法。



Answer 2:

要回答这样的为您的具体情况的问题,你必须使用诊断工具来找出你的情况是什么在起作用。

一个测试与运行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准则时处置订阅



Answer 3:

你永远不应该依赖垃圾收集干净地处理你的对象。

终结有一个最大的执行时间,并可以以任何顺序执行, Dispose会,如果处置模式是正确实施甚至没有被调用。

Dispose应清理托管资源和终结应清理非托管资源,以避免内存泄漏。 该Disposing(bool)模式将调用上都明确的Dispose ,只有在垃圾收集非托管。

明确的Dispose也可以让你更早清理,而不是等到GC收集。

具体用于订阅,事件处理等不清除的引用可能意味着,当GC不会收集,引用仍然存在,在这种情况下,物体将不会在所有收集到的。

如果你知道有根没有路,你可能不严格必须明确处理,但往往在这种情况下,有人走来后,不慎在图形保持一个引用一个对象,你知道它之前,整个图可以从不收集。



文章来源: Should I always dispose subscriptions of observables?