2009-08-28 71 views
1

我有一个类型,其中包含一个每2秒触发一次实例方法的计时器。我的问题是,当对象实例退出作用域时,不会收集对象,因为计时器线程维护引用。自引用计时器/不可收集对象

我的问题是;是否有可能在运行时确定对象具有多少引用,并且引用计数是1是否引用对同一对象的循环引用?基本上我正在考虑向定时器回调中添加代码来停止定时器,如果对象只有1个循环引用,则将堆栈引用设置为空。

感谢

public class TypeWithSelfRefresh<T> 
{ 
    private readonly IList<T> _cache = new List<T>(); 
    private Timer _refreshTimer; 

    public TypeWithSelfRefresh() 
    { 
     _refreshTimer = new Timer(delegate { ClearCache();},null,2000,2000); 
    } 

    public void ClearCache() 
    { 
     lock (_cache) 
     { 
      _cache.Clear(); 
     } 
    } 

    public void Add(T item) 
    { 
     lock (_cache) 
     { 
      _cache.Add(item); 
     } 
    } 

    public IEnumerable<T> GetItems() 
    { 
     lock (_cache) 
     { 
      foreach (T item in _cache) 
      { 
       yield return item; 
      } 
     } 
    } 
} 

回答

2

看看WeakReference

+0

'WeakReference'应该很好地解决这个问题。 – 2009-08-28 09:36:46

0

循环引用不应该阻止GC收集对象,因为它无法访问。是什么让你觉得它没有收集?你叫GC.Collect

+0

我知道实例没有收集,因为我可以在剖析器(.Net Memeory Profiler)中看到它们。 我永远不会调用GC.Collect ;-) – SuperSuperDev1234 2009-08-28 09:28:14

+0

....并且内存使用量不断增长: -/ – SuperSuperDev1234 2009-08-28 09:29:48

+0

好的,但只要超出范围,对象将不会被收集...没有办法知道GC何时会收集它。如果内存使用量达到某个阈值,可能会收集它 – 2009-08-28 09:36:31

2

问题不在于循环引用。 .NET框架处理就好了。问题在于你正在处理一个实现Dispose的对象(Timer),而没有正确处理它。

任何计时器必须实现Dispose的原因很简单。对于它的工作,它必须将自身的引用放弃到在后台运行计时器的底层机制。这是你没有直接控制的参考。要摆脱那个引用,你必须调用Dispose。