.NET Framework のリソース開放基礎(2)
.NET Frameworkのリソース開放は非常に難解です。
今回は重要メソッドである以下の2つについて説明します。
・Dispose(リソースを開放できるメソッド、自動で呼ばれることはない)
・Finalize(リソースを何時か開放するメソッド、自動で呼ばれる)
実装時の注意点は以下のとおりです。
■ Dispose
- Disposeは複数回呼ばれる可能性があるし、その場合に例外なしに呼び出せるよう実装しなくてはならない。
- DisposeとFinalizeは殆ど似たような開放処理になる。しかし、アンマネージリソースの一部は、Disposeの実装とその呼び出しでしか開放できない。
- DisposeとFinalizeを両方実装した場合、Dispose内でGC.SuppressFinalizeをする(パフォーマンス上の問題)
■ Finalize
- スレッドセーフに実装する必要はないし、複数回呼ばれることはない(GCがファイナライザを実行するスレッドは 1 つだけであることを保証している)。
- Disposeが呼ばれなかったときの対策としてリソース開放を任せることができる場合がある。アンマネージリソースの大半はFinalizeの実装で開放できるため、予防線として開放処理を実装すべき(IDisposableなオブジェクトでDisposeを呼ばなくても、リークにならない場合があるのはFinalizeのおかげ)。
- Finalizeは必ず呼び出されるわけではない。スレッドの停止等、特殊な条件で呼ばれない事がある。
→つまり、OSに関連する重大なリソース(HWNDやHDC等)の開放はFinalizeに頼るべきではない。(これについては後述、CERにも関連)。 - Finalizeを実装するとリソースの破棄に時間がかかる(Finalization Queue)
ここまではしっかり覚えておくべきです。
ついでに.NETのリソース利用におけるガイドラインを少し。
- GCが管理できないリソースの開放は難解である。だから、アンマネージリソースにSafeHandleやCriticalHandleを使える場合は必ず使う。私たちが想像がつかないようなケースにも対応している。
- 同様にGCが管理できないリソースを利用するのも難解である。GCHandle等のクラスはそれにも対応するので、自前でIntPtrなどを使うことは安全なリソース開放のためにもなるべく避けるべきである。
さて、メソッドやファイナライザによるリソースの破棄が完全に保障できない以上、サーバ系プログラムはどうすべきなのでしょうか?
Microsoftのだした1つの回答はCER(Constrained Execution Region)になります。
これについては次回。
---
[MSDN] CLR Inside Out Digging into IDisposable -- MSDN Magazine, July 2007
トラックバック
この記事のトラックバックURL:
http://app.cocolog-nifty.com/t/trackback/147973/17655442
この記事へのトラックバック一覧です: .NET Framework のリソース開放基礎(2) :






コメント