2009-08-28 20 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。