2003年07月21日
川俣晶の縁側ソフトウェア技術雑記 total 4059 count

弱い参照、WeakReferenceのIsAliveとTargetの関係

Written By: 川俣 晶連絡先

 りすと亭の過去ログ再作成の機能で、意図しない例外が起きるというレポートがありました。調べてみると、どうも、「弱い参照」関係の問題のようでした。

 りすと亭のメッセージスレッド関係の機能は、「弱い参照」の機能を使って、情報のキャッシュを実現しています。滅多に参照されないメッセージスレッドの情報はガベージコレクションで消え去って頂くけれど、消え去るまではメモリ上にあって高速にアクセス可能な状態にあります。

 既に消えているかどうかを判定するために、WeakReferenceクラスのIsAliveプロパティをチェックしていて、これがtrueであればまだあると見なして、Tagetプロパティを経由して目的のオブジェクトを取得していました。しかし、データ量が極めて膨大なリスト板の過去ログ再作成では、膨大な情報を扱うため、ガベージコレクションが頻発するようで、ここで例外が起きていたようです。つまり、IsAliveプロパティをチェックしたあとでガベージコレクションが走ると、その時点で目的のオブジェクトがメモリ上から失われていた可能性があり得るのです。

 なぜ、IsAliveプロパティをチェックするだけでOKと思ったかはもう覚えていません。何かの資料を読んでそう理解したような記憶があります。ですが、それは間違いでした。資料の誤読だったかも知れません。

 この問題について調べたところ、.NET Framework SDKのサンプルソース中に、以下のようなコメントを見つけました。

// NOTE: You are dicouraged from using the WeakReference.IsAlive property

// because the object may be killed immediately after IsAlive returns

// making the return value incorrect. If the Target property returns

// a non-null value, then the object is alive and will stay alive

// since you have a reference to it. If Target returns null, then the

// object is dead.

 dicouragedはdiscouragedの書き間違いかもしれませんが、ともかく、IsAliveに頼っては駄目、ということのようですね。

 ちなみに、MagSite1でも「弱い参照」を使っていますが、こちらのソースではIsAliveは使っていなかったので問題なしです。