C#中的弱引用

Weak References


The garbage collector cannot collect an object in use by an application while the application's code can reach that object. The application is said to have a strong reference to the object.

A weak reference permits the garbage collector to collect the object while still allowing the application to access the object. A weak reference is valid only during the indeterminate amount of time until the object is collected when no strong references exist. When you use a weak reference, the application can still obtain a strong reference to the object, which prevents it from being collected. However, there is always the risk that the garbage collector will get to the object first before a strong reference is reestablished.

Weak references are useful for objects that use a lot of memory, but can be recreated easily if they are reclaimed by garbage collection.

Suppose a tree view in a Windows Forms application displays a complex hierarchical choice of options to the user. If the underlying data is large, keeping the tree in memory is inefficient when the user is involved with something else in the application.

When the user switches away to another part of the application, you can use the WeakReference class to create a weak reference to the tree and destroy all strong references. When the user switches back to the tree, the application attempts to obtain a strong reference to the tree and, if successful, avoids reconstructing the tree.

To establish a weak reference with an object, you create a WeakReference using the instance of the object to be tracked. You then set the Target property to that object and set the object tonull. For a code example, see WeakReference in the class library.

You can create a short weak reference or a long weak reference:

  • Short

    The target of a short weak reference becomes null when the object is reclaimed by garbage collection. The weak reference is itself a managed object, and is subject to garbage collection just like any other managed object. A short weak reference is the default constructor for WeakReference.

  • Long

    A long weak reference is retained after the object's Finalize method has been called. This allows the object to be recreated, but the state of the object remains unpredictable. To use a long reference, specify true in the WeakReference constructor.

    If the object's type does not have a Finalize method, the short weak reference functionality applies and the weak reference is valid only until the target is collected, which can occur anytime after the finalizer is run.

To establish a strong reference and use the object again, cast the Target property of a WeakReference to the type of the object. If the Target property returns null, the object was collected; otherwise, you can continue to use the object because the application has regained a strong reference to it.

Use long weak references only when necessary as the state of the object is unpredictable after finalization.

Avoid using weak references to small objects because the pointer itself may be as large or larger.

Avoid using weak references as an automatic solution to memory management problems. Instead, develop an effective caching policy for handling your application's objects.




WeakReference Class

The WeakReference type exposes the following members.

  Name Description
Public method Supported by the XNA Framework Supported by Portable Class Library WeakReference(Object) Initializes a new instance of the WeakReference class, referencing the specified object.
Public method Supported by the XNA Framework Supported by Portable Class Library WeakReference(Object, Boolean) Initializes a new instance of the WeakReference class, referencing the specified object and using the specified resurrection tracking.
Protected method WeakReference(SerializationInfo, StreamingContext) Initializes a new instance of the WeakReference class, using deserialized data from the specified serialization and stream objects.
Top
  Name Description
Public property Supported by the XNA Framework Supported by Portable Class Library IsAlive Gets an indication whether the object referenced by the current WeakReference object has been garbage collected.
Public property Supported by the XNA Framework Supported by Portable Class Library Target Gets or sets the object (the target) referenced by the current WeakReference object.
Public property Supported by the XNA Framework Supported by Portable Class Library TrackResurrection Gets an indication whether the object referenced by the current WeakReference object is tracked after it is finalized.
Top
  Name Description
Public method Supported by the XNA Framework Supported by Portable Class Library Equals(Object) Determines whether the specified Object is equal to the current Object. (Inherited from Object.)
Protected method Supported by the XNA Framework Supported by Portable Class Library Finalize Discards the reference to the target represented by the current WeakReference object. (Overrides Object.Finalize().)
Public method Supported by the XNA Framework Supported by Portable Class Library GetHashCode Serves as a hash function for a particular type. (Inherited from Object.)
Public method GetObjectData Populates a SerializationInfo object with all the data needed to serialize the current WeakReference object.
Public method Supported by the XNA Framework Supported by Portable Class Library GetType Gets the Type of the current instance. (Inherited from Object.)
Protected method Supported by the XNA Framework Supported by Portable Class Library MemberwiseClone Creates a shallow copy of the current Object. (Inherited from Object.)
Public method Supported by the XNA Framework Supported by Portable Class Library ToString Returns a string that represents the current object. (Inherited from Object.)
Top

A weak reference allows the garbage collector to collect an object while still allowing an application to access the object. If you need the object, you can still obtain a strong reference to it and prevent it from being collected. For more information about how to use short and long weak references, see Weak References.

The following example demonstrates how you can use weak references to maintain a cache of objects as a resource for an application. The cache is constructed using an IDictionary<TKey, TValue> of WeakReference objects keyed by an index value. The Target property for the WeakReference objects is an object in a byte array that represents data.

The example randomly accesses objects in the cache. If an object is reclaimed for garbage collection, a new data object is regenerated; otherwise, the object is available to access because of the weak reference.

C#
VB
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%
//



C#中的弱引用(WeakReference)

我们通俗用的都是对象的强引用,若是有强引用存在,GC是不会收受接管对象的。我们能不克不及同时对峙对对象的引用,而又可以让GC须要的时辰收受接管这个对象呢?.NET中供给了WeakReference来实现。弱引用可以让您对峙对对象的引用,同时容许GC在须要时开释对象,收受接管内存。对于那些创建便宜但花费多量内存的对象,即欲望对峙该对象,又要在应用法度须要时应用,同时欲望GC须要时收受接管时,可以推敲应用弱引用。弱引用应用起来很简单,看下面的代码:
Object obj = new Object();
WeakReference wref = new WeakReference( obj );
obj = null;

第一行代码新建了一个新的对象,这里叫它对象A,obj是对对象A的强引用。接着第二行代码新建了一个弱引用对象,参数就是对象A的强引用,第三行代码开释掉对对象A的强引用。这时若是GC进行收受接管,对象A就会被收受接管。
如何在取得对象A的强引用呢?很简单,请看代码2:

Object obj2 = wref.Target;
if( obj2 != null )
{
   // 做你想做的事吧。
}
else
{
// 对象已经被收受接管,若是要用必须新建一个。
}

只要显示的将弱引用的Target属性附值就会获得弱引用所代表对象的一个强引用。不过在应用对象之前要对其可用性进行搜检,因为它可能已经被收受接管了。如 果你获得的是null(VB.NET下为Nothing),注解对象已经被收受接管,不克不及再用了,须要从头分派一个。若是不是null,就可以宁神大胆的用 了。
接下来让我们看WeakReference的别的一个版本,请看代码3:
// public WeakReference(
//   object target,
//   bool trackResurrection
//);


Object obj1 = new Object();

Object obj2 = new Object();

WeakReference wref1 = new WeakReference( obj1, false );

WeakReference wref2 = new WeakReference( obj2, true );

WeakReference的别的一个版本有两个参数,第一个参数和我们前面用的版本的一样。第二个参数让我们看一下他的原型,bool trackResurrection,跟踪复生,是个bool型,就是是否跟踪复生。前面的文章中我提到过须要Finalize的对象在终极开释前会有一 次复生,我们可能可以猜到第二个参数默示的意思了。若是我们第二个参数给false,这个弱引用就是一个short weak reference(短弱引用),当GC收受接管时,发明根中没有这个对象的引用了,就认为这个对象无用,这时短弱引用对这个对象的跟踪到此为止,弱引用的 Target被设置为null。前面的一个参数的机关函数版本新建的弱引用为短弱引用。若是第二个参数给true,这个弱引用就是一个long weak reference(长弱引用)。在对象的Finalize办法没有被履行以前,Target都可用。不过这是对象的某些成员变量也许已经被收受接管,所以使 用起来要想当警惕。
如今让我们看看WeakReference是如何实现的。很显然WeakReference不克不及直接的引用目标对象,WeakReference的 Target属性的get/set是两个函数,从某处查到目标对象的引用返回,而不是我们最常用写的那样直接返回或者设置一个私有变量。GC保护了两个列 表来跟踪两种弱引用的目标对象,在一个 WeakReference对象创建时,它在响应的列表中找到一个地位,将目标对象的引用放入,很显然,这两个列表不是根的一项目组。在GC进行内存收受接管的 时辰,若是要收受接管某一个对象,会搜检弱引用的列表,若是保存着这个对象的引用,则将其设为null。 
public class AspPage : Page
{
private static ArrayList __ENCList = new ArrayList();

   [DebuggerNonUserCode]
        public AspPage()
        {
            base.Load += new EventHandler(this.Page_Load);
            ArrayList list = __ENCList;
            lock (list)
            {
                __ENCList.Add(new WeakReference(this));
            }
        }

}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值