2013-02-13 9 views
8

は、このコードを考えてみましょう:GC.CollectweakRef.IsAliveを確認した後とweakRef.Targetを使用する前に実行するため安全な方法で弱い参照のターゲットを取得する方法

var weakRef = new WeakReference(new StringBuilder("Mehran")); 
if (weakRef.IsAlive) 
{ 
    // Garbage Collection might happen. 
    Console.WriteLine((weakRef.Target as StringBuilder).ToString()); 
} 

それが可能です。

私はこれに間違っていますか?可能であれば、それを行う安全な方法がありますか?

たとえば、weakRef.GetTargetIfIsAlive()のようなAPIが適切です。

+1

http://msdn.microsoft.com/en-gb/library/ms404247.aspx –

+1

最初に強力な参照にキャストしてから、「ヌル」を確認する必要があります。あなたの強い参照があらかじめヌルでないことを保証する方法はありません。 –

答えて

12

そのAPIは既に存在しています。 weakRef.Targetは、オブジェクトがすでにガベージコレクションされている場合はnullを返します。

StringBuilder sb = weakRef.Target as StringBuilder; 
if (sb != null) 
{ 
    Console.WriteLine(sb.ToString()); 
} 
1

ターゲットのローカルコピーをとり、nullを確認します。ターゲットが収集された場合

WeakReference.Targetnullを返しますが、あなたは懸念は、それがあなたの.IsAlive小切手やターゲットを得るの間収集だということですね。

var weakRef = new WeakReference(new StringBuilder("Mehran")); 

if (weakRef.IsAlive) 
{ 
    var stringBuilder = weakRef.Target as StringBuilder; 

    if (stringBuilder != null) 
    { 
     Console.WriteLine(stringBuilder.ToString()); 
    } 
} 

Console.WriteLine((weakRef.Target as StringBuilder).ToString());は、キャストが失敗した場合にnull参照例外をスローします。

+0

なぜ 'weakRef.IsAlive'のチェックが必要なのか疑問に思っていたので、@ supercatが質問に答えましたので、チェックする必要はありません。 – mehrandvd

+1

@mehrandvd必要ではないかもしれませんが、私は元の質問に基づいていたので、この例でのみ使用しました。それを使うのは害ではありませんが、 'as'キャストと' .Target'のヌルチェックでは、無意味なチェックである可能性があります。 –

+1

@TrevorPilley: '真の値がターゲットを取得することを意味するならば、' WeakReference'に 'IsAlive'を使用することは無意味です。いくつかのガベージコレクタで、 'if(wr1.IsAlive && wr2.IsAlive && wr3.IsAlive){Foo wt1 = wr1.Target Foo、wt2 = wr2.Target Foo、wt3 = wr3.Target Foo; if(wr1!= null && wr2!= null && wr3!= null){... 3つすべてを使用...}}は、たとえばGCへの参照が最後のGC以降に作成されたかどうかを追跡することにより、並行ガベージコレクタが機能します。このようなGCで、wr3が死んでいたのにwr1とwr2が生きていたら... – supercat

9

IsAliveプロパティは、ターゲットが生きていればそれを使用したいと思うコードの利益のために存在するのではなく、ターゲットが死んだが興味がないかどうかを知りたいコードの利益のために存在するいずれにしてもそれにアクセスすることができます。コードがTargetをnullに対してテストすると、Targetは瞬間的に強力なルート参照(nullをテストするコード)を持ち、そのようなルート参照を生成するとオブジェクトがガベージコレクションされない可能性がありますそうでなければそうなるでしょう。 Targetにまだコードが無効になっているかどうかを調べる以外は、コードが参照を取得する理由はありません。代わりにIsAliveを単にテストし、falseを返す場合は適切な処置をとることができます。

+0

なぜIsAliveが存在するのか不思議でした。これは非常に賢い答えです、ありがとう。 – mehrandvd

+1

@mehrandvd: 'WeakReference'から' Target'を取り出す行為が、参照が直ちに破棄されたとしても、そのオブジェクトが次のサイクル*で収集されないようにする同時GCを想像するのは難しくありません。このようなシステムでは、オブジェクトがもはや必要なくなり、 'IsAlive'ではなく' Target'を使用するとすぐに、何らかのアクションを起こしたいコードが、問題のオブジェクトを永遠に生き残らせる可能性があります。 – supercat

関連する問題