何となく Blog by Jitta
Microsoft .NET 考

目次

Blog 利用状況
  • 投稿数 - 761
  • 記事 - 18
  • コメント - 36161
  • トラックバック - 222
ニュース
  • IE7以前では、表示がおかしい。div の解釈に問題があるようだ。
    IE8の場合は、「互換」表示を OFF にしてください。
  • 検索エンジンで来られた方へ:
    お望みの情報は見つかりましたか? よろしければ、コメント欄にどのような情報を探していたのか、ご記入ください。
It's ME!
  • はなおか じった
  • 世界遺産の近くに住んでます。
  • Microsoft MVP for Visual Developer ASP/ASP.NET 10, 2004 - 9, 2011
広告

記事カテゴリ

書庫

日記カテゴリ

ギャラリ

その他

わんくま同盟

同郷

 

もと:re: COM リリース:お勧めではないが、こんな方法も...

せっかくなので、正当な方法についてもリンクか何かで示して欲しいなぁ。

「じゃんぬさんのサイトにもありますが、try - finally で COM オブジェクトを解放します。」と書いていたので、良いかなぁ、、、と思っていたので、ご指摘いただいたので、追加エントリ。せっかくなので、どの様な考えのもとに先のエントリがあるのか、なぜ勧めないのかにつても、書いてみます。


まず、先のエントリでは「なぜ Excel アプリケーションが終了するのか」と、「なぜお勧めしないのか」について、説明します。

プログラミングの原則として、「使ったものは元に戻す」ということがあります。これは、どんな言語であろうと、共通することです。「使ったもの」とは、メモリを含むリソース、資源です。

Java や Microsoft CL など、一部の言語では、メモリについて、ガーベッジ コレクションなどの方法によって、フレームワークが管理します。このため、C 言語のように、開発者が最初から最後まで管理する必要がなくなっています。

以降、Microsoft CL にフォーカス

ここで、フレームワークが管理するリソース(マネージド リソース)と、開発者が管理しなければならないリソース(アンマネージド リソース)を混同しているケースが散見されます。特に古くからの VB ユーザに見られる、「変数には Nothing を放り込みました」というようなケースです。

確かに、マネージド リソースについては、変数に Nothing を放り込むことで、確保されているメモリエリアを参照するものを無くし、ガベージ コレクタが動作するときに回収してもらうことが出来ます。このとき、フレームワークにはじめから用意されているクラスについては、適切にアンマネージド リソースを解放する動作も行われると期待できるため、ある意味、正しいでしょう。遅くとも、プログラムが終了するときには、必ず解放されます。

ただし、菊地さんによると、IDE が生成するコードは信用できないときもあるようです。

しかし、「解放されるタイミングが、解放したいタイミングと同じか」という視点で見れば、誤りになります。先のエントリは、この、「解放されるタイミングを、解放したいタイミングと同じにする」ことが目標となります。


では、どうやって同じにしましょうか。「参照されていないメモリは、ガーベッジ コレクションのときに回収される」ことを利用します。つまり、参照しなくして、ガーベッジ コレクションが動作するように指示するわけです。

ところが、やっかいなのが 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
コメント
  • # re: COM リソースの解放(その1)
    Jitta
    Posted @ 2006/07/19 22:45
    「ガーベッジ」と「ガベージ」が混ざっている。。。

    > 暗黙参照をこのインスタンスの中に作り
     メソッドを抜けるとスコープが外れるから、、、ってことなんだけど、書いているときは「スコープ」が出てこなかった。。。
タイトル
名前
Url
コメント