对IDisposable的弱引用

时间:2019-03-28 18:05:18

标签: c# winforms weak-references

我有一个类,其中包含一个WeakReference,该对象指向实现IDisposable的对象。处置对象后,要经过一段时间才能收集垃圾。在这段时间内,WeakReference仍然可以使用。这可能会导致意外行为,因为我们现在正在对已处置的对象进行调用。

有人建议使用这种方法来处理这种情况吗?检查弱参考是否已处置目标等?

背景: 我们有一个带有控制器的WinForms应用程序,该控制器保存数据。多个UI控件可能在任何给定时间呈现数据。表单添加和删除控件(并在删除它们时调用Dispose),但是不知道控件在做什么或需要什么数据。以前,控件将订阅来自控制器的事件以在数据更新时接收通知。这会导致内存泄漏。为了解决这个问题,控制器现在保留对控件的弱引用,并通知仍然存在的控件。

2 个答案:

答案 0 :(得分:2)

由于IDisposableWeakReference具有互斥语义,因此您需要选择一个。将它们组合在一起是危险的,因为在处理后,一个对象很可能会具有不一致的状态,因此不适合重复使用。 IDisposable表示您希望控制对象的生命周期,并且不会收回。这就像将某些东西放到垃圾箱中,然后说:“我已经完成了这件事,现在我不在乎这会发生什么。” WeakReference的语义就像是在垃圾箱附近放东西,然后说:“我要在30分钟左右回来,如果没人把它放进垃圾箱,我会把它拿回来,但是如果它在我里面不在乎”。

弱引用意味着它们引用的对象没有很长的寿命,因为它们有利于快速回收内存,但同时它们也提供了一些重用的机会,因此在您的情况下,您可以完全依靠{{ 1}}:

WeakReference<T>

答案 1 :(得分:0)

以防万一其他人偶然发现了这个问题,他们解决了我的方法,那就是使被引用的对象在处置后具有明确的行为(根据Alexei Levenkov的评论)。最简单的方法是在处理完对象后忽略函数调用。

public void OnDataChanged(object model)
{
    if (IsDisposed)
    {
        return;
    }
    ...
    // method implementation
}

这仅在从弱引用中调用单个函数时是必需的。

多线程处理不是问题,因为这些都是UI对象,并且调用Invoke和BeginInvoke才能进行修改它们的调用。