WeakReference to IDisposable

问题描述 投票:-1回答:2

我有一个类,持有WeakReference指向一个实现IDisposable的对象。在处理对象之后,在垃圾收集之前有一段时间。在此期间,仍然可以使用WeakReference。这可能会导致意外行为,因为我们现在正在对已经处置的对象进行调用。

有没有人有一个建议的方法来处理这个问题,如果目标已被处置,检查弱引用等等?

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

c# winforms weak-references
2个回答
2
投票

由于IDisposableWeakReference具有互斥语义,因此您需要选择单一语义。将它们组合是危险的,因为在处理之后,物体很可能具有不适合重复使用的不一致状态。 IDisposable意味着你想要控制物体的生命周期而不会收回。这就像把东西放进垃圾箱并说:“我已经完成了这件事,现在我并不关心那会发生什么”。 WeakReference的语义就像在垃圾箱附近放一些东西说:“我会在30分钟左右回来,如果没有人把它放进这个垃圾箱里我会收回它,但是如果它在里面我不在乎”。

弱参考意味着它们引用的对象没有很长的寿命,它们对快速记忆回收有好处,但同时它们有一些机会被重用,所以在你的情况下你可以完全依赖WeakReference<T>

MyType instance;
if (weakRef.TryGetTarget(out instance))
{
    // resurrected, still can use it
}
else
{
   // object is collected, the new one should be created
}

0
投票

为了防止其他人偶然发现这个问题他们解决它的方法是让被引用的对象在被处置后具有明确定义的行为(根据Alexei Levenkov的评论)。最简单的方法是在处理对象后忽略函数调用。

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

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

多线程不是问题,因为它们是UI对象,并且已经需要Invoke和BeginInvoke来调用它们。

© www.soinside.com 2019 - 2024. All rights reserved.