.NET框架提供了另一有趣的特色,被用於實現多樣的高速緩存。在.NET中弱引用通過System.WeakReference類實現。弱引用為引用的對象提供一項機制,使被引用的對象能夠被垃
圾收集器作用。ASP.NET高速緩存就使用了弱引用。如果內存使用率太高,高速緩存將被清除。
強制垃圾收集 .NET框架為開發者提供System.GC類來控制垃圾收集器的一些方面。垃圾收集可以通過調用GC.Collect方法強制執行。通常建議不要手動的調用垃圾收集器,而將其設置為自動方式。在某些情況下,開發者會發現強制垃圾收集將推進性能。但是,使用這個方法需要非常小心,因為在垃圾收集器運行時將延緩當前執行的線程。GC.Collect方法不應位於可能被經常調用的地方。這樣做將使應用程序的性能降級。
構造函數:
WeakReference 初始化 WeakReference 類的新實例。 此構造函數重載不能在基於 Silverlight 的應用程序中實現。
WeakReference(Object) 引用指定的對象初始化 WeakReference 類的新實例。
WeakReference(Object, Boolean) 初始化 WeakReference 類的新實例,引用指定的對象並使用指定的復活跟蹤。
屬性:
IsAlive 獲取當前 WeakReference 對象引用的對象是否已被垃圾回收的指示。
Target 獲取或設置當前 WeakReference 對象引用的對象(目標)。
TrackResurrection 獲取當前 WeakReference 對象引用的對象在終止后是否會被跟蹤的指示。
我們考慮使用弱引用的時候:
對象稍后可能被使用,但不是很確定。(如果確定要使用,就應該用強引用)
如果需要,對象可以重新被構造出來(比如數據庫構造)。
對象占相對比較大的內存(一般大於幾KB以上)
在某些場合,例如緩存某些大數據對象的時候,會遇到內存與時間的兩難境況,如果讓大對象過快的過期,那么每次創建對象會消耗過多的性能,反之,保持了過多的大對象,那
么內存將耗盡,反而降低速度。 如果內存尚且足夠,那么GC就不會回收大對象占用的內存,那么弱引用就是可到達的,也就是說可以重用這個對象,達到緩存的目的。如果內存不足,那么GC就會不得不去回收那些大對象,從而釋放內存空間。
下面的代碼示例演示如何使用弱引用將對象的緩存作為應用程序的資源進行維護。 此緩存是使用以索引值為關鍵字的 WeakReference 對象的 IDictionary(Of TKey, TValue) 構建的。 WeakReference 對象的 Target 屬性是一個表示數據的字節數組中的對象。
此示例將隨機訪問緩存中的對象。 如果通過垃圾回收來回收對象,則將重新生成新的數據對象;否則,該對象會因弱引用而可訪問。
using System; using System.Collections.Generic; public class Program { public static void Main() { // Create the cache. int cacheSize = 50; Random r = new Random(); Cache c = new Cache(cacheSize); string DataName = ""; // Randomly access objects in the cache. for (int i = 0; i < c.Count; i++) { int index = r.Next(c.Count); // Access the object by // getting a property value. DataName = c[index].Name; } // Show results. double regenPercent = c.RegenerationCount * 100 / c.Count; Console.WriteLine("Cache size: {0}, Regenerated: {1}%", c.Count.ToString(), regenPercent.ToString()); } } public class Cache { // Dictionary to contain the cache. static Dictionary<int, WeakReference> _cache; // Track the number of times an // object is regenerated. int regenCount = 0; public Cache(int count) { _cache = new Dictionary<int, WeakReference>(); // Add data objects with a // short weak reference to the cache. for (int i = 0; i < count; i++) { _cache.Add(i, new WeakReference(new Data(i), false)); } } // Returns the number of items in the cache. public int Count { get { return _cache.Count; } } // Returns the number of times an // object had to be regenerated. public int RegenerationCount { get { return regenCount; } } // Accesses a data object from the cache. // If the object was reclaimed for garbage collection, // create a new data object at that index location. public Data this[int index] { get { // Obtain an instance of a data // object from the cache of // of weak reference objects. Data d = _cache[index].Target as Data; if (d == null) { // Object was reclaimed, so generate a new one. Console.WriteLine("Regenerate object at {0}: Yes", index.ToString()); d = new Data(index); regenCount++; } else { // Object was obtained with the weak reference. Console.WriteLine("Regenerate object at {0}: No", index.ToString()); } return d; } } } // This class creates byte arrays to simulate data. public class Data { private byte[] _data; private string _name; public Data(int size) { _data = new byte[size * 1024]; _name = size.ToString(); } // Simple property. public string Name { get { return _name; } } } // Example of the last lines of the output: // // ... // Regenerate object at 36: Yes // Regenerate object at 8: Yes // Regenerate object at 21: Yes // Regenerate object at 4: Yes // Regenerate object at 38: No // Regenerate object at 7: Yes // Regenerate object at 2: Yes // Regenerate object at 43: Yes // Regenerate object at 38: No // Cache size: 50, Regenerated: 94% //