@IT会議室は、ITエンジニアに特化した質問・回答コミュニティ「QA@IT」に生まれ変わりました。ぜひご利用ください。
- PR -

VB.NETでEXCELが終了しない。

1
投稿者投稿内容
kai
会議室デビュー日: 2003/05/13
投稿数: 4
投稿日時: 2003-05-14 00:09
はじめまして。
いつも大変参考にさせてもらっています。
そこでどうしても解決できない問題が発生しましたので
アドバイスをよろしくお願いします

VB.NETでEXCELの表示を行い処理後、終了したのにもかかわらず
メモリから開放されない現象が起きています。
この手の問題はログにありましたので参考にし四苦八苦しながら
「GC.Collect()」等を追加して見ましたが結果は変わりませんでした。

ログに解決策が出ているような問題を再度聞くのはとても心苦しいの
ですが、よろしくお願いします。

以下ソースです。

Private Function fnPrint
Dim objExcel As Object

objExcel = CreateObject("Excel.Application")
objExcel.Application.Workbooks.Open(C_EXCEL_SHEET)

'/* ここで処理実行(現状コメントアウト)*/

objExcel.Application.Quit()
objExcel = Nothing
End Function


[ メッセージ編集済み 編集者: kai 編集日時 2003-05-14 00:15 ]
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2003-05-14 08:31
こんにちは。

 もう一度ログを見直してください。どこかに「エクセルを作るオブジェクトを解放してやればいいようです」と書いたはず。。。
kai
会議室デビュー日: 2003/05/13
投稿数: 4
投稿日時: 2003-05-14 09:22
返答ありがとうございます。

多分、言われているログの内容は見させていただきました。
「エクセルにデータをコピーするのに時間がかかるので、
-------------中略-------------
スレッド処理クラス自身をNothingしてやらなければいけなかったようです。」
で解決していたと思います。

しかし、私の方ではこの処理に関しては単純にFUNCTION内でクローズさせていますので
「スレッド処理クラス自身をNothing」と状況が違うのではないかと思いました。

上記のログの中に、
Dim ww As Object
For Each ww In objExcel.Workbooks
ww.Close(False)
Next
と言う文脈も見つけましたので「Quit」の前に入れてみましたが効果がありません。
私の方の認識不足であれば申し訳ありませんが、教えてください。
よろしくお願いします。

[ メッセージ編集済み 編集者: kai 編集日時 2003-05-14 09:24 ]
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2003-05-14 10:09
 すみません、Tipsを見て、考えが変わりました。

 エクセルが終了される=エクセルが起動したために使用されているメモリが解放されるのは、ガベージコレクタがガベージ収集を行ったときです。ガベージコレクタが「ガベージ」と判断するのは、そのメモリへの参照が全て外れているときです。そして、ガベージコレクタは、デフォルトでは直近に確保されて参照が外れているメモリしか解放しません(「ガベージ・コレクタを明示的に動作させるには?」より、私なりに解釈)。

 これから想像するに、エクセルを終了させるには、エクセルへの参照をすべて外し、ガベージコレクタを明示的に起動(GC.Collect()をコール)し、その時に、すべてのメモリを破棄させる指示をすればよい・・・ということでしょう。

 参照記事の最後に『なお、85,000byte以上のオブジェクトは常にジェネレーション2に置かれ、ジェネレーション増加の対象にならないとされている。』とあります。エクセルオブジェクトは、これに当たるのでしょう。ですから、同記事を参照に、ジェネレーション2まで解放されるようにすれば、終了できると思います。
kai
会議室デビュー日: 2003/05/13
投稿数: 4
投稿日時: 2003-05-14 11:38
ありがとうございます。
大変参考になりました。

その情報を元に出来る限りの事をした上で試した所

Private Function fnPrint
  Dim objExcel As Object

  objExcel = CreateObject("Excel.Application")
  objExcel.Application.Workbooks.Open(C_EXCEL_SHEET)

  objExcel.Application.Quit()
  objExcel = Nothing
  GC.Collect()
End Function

で終了されました。
教えていただいた知識だと「ガベージコレクタがガベージ収集を行った」
のだと思いますが、

Private Function fnPrint
  Dim objExcel As Object
  
  '/* ここの位置でoracleの制御 */
  '/* EXCELへの参照はまったく行っていない */

  objExcel = CreateObject("Excel.Application")
  objExcel.Application.Workbooks.Open(C_EXCEL_SHEET)

  objExcel.Application.Quit()
  objExcel = Nothing
  GC.Collect()
End Function

の場合は、EXCELが終了しないようです。
と言う事は「ガベージコレクタ」関係ではないかと言う予想まではたどり着けました。
ありがとうございます。



[ メッセージ編集済み 編集者: kai 編集日時 2003-05-14 11:40 ]

[ メッセージ編集済み 編集者: kai 編集日時 2003-05-14 11:41 ]
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2003-05-14 11:56
引用:

kaiさんの書き込み (2003-05-14 11:38) より:
Private Function fnPrint
  Dim objExcel As Object
  
  '/* ここの位置でoracleの制御 */
  '/* EXCELへの参照はまったく行っていない */

  objExcel = CreateObject("Excel.Application")
  objExcel.Application.Workbooks.Open(C_EXCEL_SHEET)

  objExcel.Application.Quit()
  objExcel = Nothing
  GC.Collect()
End Function

の場合は、EXCELが終了しないようです。


 え?いや、だから、GC.Collect()ではなくて、GC.Collect(2)…
kai
会議室デビュー日: 2003/05/13
投稿数: 4
投稿日時: 2003-05-14 12:14
申し訳ありません。

言葉足らずでしたが、
GC.Collect()
GC.Collect(2)
双方で試したのですが、終了しないのです。

コメントアウトし確認した所
上部処理が有るか無いかで結果が変わるようなのです。
ちなみに上部処理ではOracle用のクラスを参照していたり
していますがEXCEL関係にはまったく触れていない部分です。
1

スキルアップ/キャリアアップ(JOB@IT)