6

オブジェクトクラスのデリゲートメソッドでクラスを使用するWeakReferenceと、オブジェクトクラスはGCによって収集されますが、それの別のコピーがWeakReference?に存在しているように見えます。

言葉で説明するのは難しいと思います。例を挙げましょう。私は次のオブジェクトクラスを持っていますTestObject

class TestObject
{
    public string message = "";

    private delegate string deleg();

    public TestObject(string msg)
    {
        message = msg;
    }

    public Delegate GetMethod()
    {
        deleg tmp = this.TestMethod;
        return tmp;
    }

    public string TestMethod()
    {
        return message;
    }

}

今、私のメインアプリケーションでは、を介してメソッドを参照しようとしTestMethodTestObjectWeakReferenceます。意図はTestObject、すべてのハード参照がなくなったときにGCによって収集できるようにすることです。これは私のメインアプリケーションがどのように見えるかです:

static void Main(string[] args)
    {
        var list = new List<WeakReference>();
        var obj = new TestObject("Hello 1");
        list.Add(new WeakReference(obj.GetMethod()));
        Console.WriteLine("Initial obj: " + ((Delegate)list[0].Target).DynamicInvoke());      //Works fine
        obj = null;     //Now, obj is set to null, the TestObject("Hello 1") can be collected by GC
        GC.Collect();   //Force GC
        Console.WriteLine("Is obj null: " + ((obj) == null ? "True" : "False"));
        Console.WriteLine("After GC collection: " + ((Delegate)list[0].Target).DynamicInvoke());
        Console.ReadKey();
    }

上記のコードを実行したときの出力は次のとおりです。

ここに画像の説明を入力してください

これが奇妙なことです。最初の行では、初期化されたばかりで、への参照を保持していたため、obj印刷できました。すべて正しい。次に、withに設定し、GCを強制的に収集しました。したがって、出力の2行目では、はnullになります。最後に、最後の行で、GCが離れて収集したので、出力にaをスローするか、何も出力しないことを期待しています。ただし、実際には出力の最初の行と同じものが出力されます。この時点でGCによって収集されるべきではありませんか?!"Hello 1"objTestObjectobjnullobj = nullobjtrueobjNullReferenceExceptionTestObject

これは、objをnullに設定した後TestObject、最初に保持されたものが後でGCによって収集されたかどうかという疑問を投げかけます。obj

オブジェクト全体をに渡した場合WeakReference、つまり、new WeakReference(obj)デリゲートをに渡すのではなく、に渡した場合はWeakReference、完全に機能します。

残念ながら、私のコードではWeakReference、デリゲートに渡す必要があります。WeakReferenceGCがデリゲートを参照するだけでオブジェクトを収集できるように、を正しく機能させるにはどうすればよいですか?

4

2 に答える 2

6

問題はあなたのテストにあると思います-フレームワークではありません。ローカル変数をnullに設定しても、期待どおりの結果が得られないようです。ローカル変数を完全にスキップすると、「後」の行で予期されるNullReferenceExceptionが発生します。

static void Main(string[] args)
{
    var list = new List<WeakReference>();
    //var obj = new TestObject("Hello 1");
    list.Add(new WeakReference(new TestObject("Hello 1").GetMethod()));
    Console.WriteLine("Initial obj: " + ((Delegate)list[0].Target).DynamicInvoke());      //Works fine
    //obj = null;     //Now, obj is set to null, the TestObject("Hello 1") can be collected by GC
    GC.Collect();   //Force GC
    //Console.WriteLine("Is obj null: " + ((obj) == null ? "True" : "False"));
    Console.WriteLine("After GC collection: " + ((Delegate)list[0].Target).DynamicInvoke());
    Console.ReadKey();
}
于 2012-12-23T00:07:35.357 に答える
0

実際には、WeakReferenceがDelegateを参照する以外に何もないため、例は期待どおりに実行されます。したがって、「obj = null」行をコメントアウトしても、GCはそれを収集できます。

これが私の結果です

おそらく、(メインスレッドを除いて)別のスレッドでコードを実行しているためですか?

于 2013-10-15T08:05:42.423 に答える