もと:re: COM リリース:お勧めではないが、こんな方法も...
せっかくなので、正当な方法についてもリンクか何かで示して欲しいなぁ。
「じゃんぬさんのサイトにもありますが、try - finally で COM オブジェクトを解放します。」と書いていたので、良いかなぁ、、、と思っていたので、ご指摘いただいたので、追加エントリ。せっかくなので、どの様な考えのもとに先のエントリがあるのか、なぜ勧めないのかにつても、書いてみます。
まず、先のエントリでは「なぜ Excel アプリケーションが終了するのか」と、「なぜお勧めしないのか」について、説明します。
プログラミングの原則として、「使ったものは元に戻す」ということがあります。これは、どんな言語であろうと、共通することです。「使ったもの」とは、メモリを含むリソース、資源です。
Java や Microsoft CL など、一部の言語では、メモリについて、ガーベッジ コレクションなどの方法によって、フレームワークが管理します。このため、C 言語のように、開発者が最初から最後まで管理する必要がなくなっています。
以降、Microsoft CL にフォーカス
ここで、フレームワークが管理するリソース(マネージド リソース)と、開発者が管理しなければならないリソース(アンマネージド リソース)を混同しているケースが散見されます。特に古くからの VB ユーザに見られる、「変数には Nothing を放り込みました」というようなケースです。
確かに、マネージド リソースについては、変数に Nothing を放り込むことで、確保されているメモリエリアを参照するものを無くし、ガベージ コレクタが動作するときに回収してもらうことが出来ます。このとき、フレームワークにはじめから用意されているクラスについては、適切にアンマネージド リソースを解放する動作も行われると期待できるため、ある意味、正しいでしょう。遅くとも、プログラムが終了するときには、必ず解放されます。
しかし、「解放されるタイミングが、解放したいタイミングと同じか」という視点で見れば、誤りになります。先のエントリは、この、「解放されるタイミングを、解放したいタイミングと同じにする」ことが目標となります。
では、どうやって同じにしましょうか。「参照されていないメモリは、ガーベッジ コレクションのときに回収される」ことを利用します。つまり、参照しなくして、ガーベッジ コレクションが動作するように指示するわけです。
ところが、やっかいなのが COM の暗黙参照です。変数 excel を、ExcelApplication クラスのインスタンスとすると、excel.WorkBooks.WorkBook[1]
とすることで、WorkBooks と WorkBook に対する暗黙参照が出来てしまいます。この暗黙参照があるために、Excel アプリケーション オブジェクトは、ガーベッジ コレクションが動作しても終了しません。
そこで先のエントリでは、使用したいクラスが直接 Excel を扱うのではなく、ExcelInterface というクラスを経由して使うことにしました。暗黙参照をこのインスタンスの中に作り、このインスタンスへの参照を無くすことで、間接的に Excel アプリケーション オブジェクトへの参照も無くしたわけです。クラス(インスタンス)メンバ変数については、オブジェクトそのものが参照を保持していますから、明示的に参照を解除してやる必要があります。その上でガーベッジ コレクションを動作させるので、Excel アプリケーション オブジェクトも、(Quit していれば)終了してくれます。
では、なぜ、「お勧めではない」のか。ガーベッジ コレクションを呼ばなければならないからです。
ガーベッジ コレクションは、アプリケーションのすべてのマネージド リソースが、回収可能か検査します。そして、回収可能なものについて、回収します。特に、GC.Collect()
、GC.Collect(0)
は、すべてのジェネレーションのマネージド リソースを検査します。そして、このとき回収されなかったマネージド リソースは、(私の理解が正しければ)ジェネレーションが上がります。
また、ガーベッジ コレクションは、「マネージド リソース」を回収するもので、「アンマネージド リソース」を解放するものではありません。アンマネージド リソースを解放するために、マネージド リソースを回収させるというこの方法は、ガーベッジ コレクションの目的から外れているのではないでしょうか。
クラスの開発者も、何が(クラスまたはインスタンス メンバなので)解放しなければならないのか、気を遣わなければなりません。使用者にも、Dispose のコールと GC.Collect のコールを強要します。わかっていて使う分には、特に問題はないでしょうが、他の人がメンテナンスするかもしれない、このような誰が目にするかわからない場所に提示する、時間をおいてメンテナンスするかもしれない、ような場合は、使わない方がよいでしょう。
推奨される方法については、次回。。。
投稿日時 : 2006年7月19日 22:37