C#弱引用

12160 ワード

.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以上)
 
ある場合、たとえば大きなデータ・オブジェクトをキャッシュする場合、メモリと時間の2つの困難な状況に遭遇します.大きなオブジェクトを期限切れにしすぎると、オブジェクトを作成するたびにパフォーマンスが消費され、逆に大きなオブジェクトを維持しすぎると、
メモリが消費され、かえって速度が低下します.メモリが十分であれば、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%
//