C# と VB.NET の質問掲示板

わんくま同盟

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト


(過去ログ 91 を表示中)
■54149 / )  Re[7]: VB.NETでエクセルファイル操作
□投稿者/ 魔界の仮面弁士 (1857回)-(2010/10/06(Wed) 20:06:19)
2010/10/06(Wed) 20:06:49 編集(投稿者)

No54145 (おじゃ さん) に返信
> 原因は、For Eachにあると思うのですが、理由がわかりません。

原因と理由の回答になっているかは分かりませんが、

 For Each objBook In objBooks
  MsgBox(objBook.FullName)
  Marshal.ReleaseComObject(objBook)
 Next

という処理においては、実際には下記に相当する処理が実行されます。

 'Dim objEnum As Object = CallByName(objBooks, "_NewEnum", vbGet)
 'Dim objEnum As Object = CallByName(objBooks, "[DispID=-4]", vbMethod)
 Dim objEnum As IEnumerator = objBooks.GetEnumerator()
 Do While objEnum.MoveNext()
  objBook = objEnum.Current
  MsgBox(objBook.FullName)
  Marshal.ReleaseComObject(objBook)
 Loop

で、このように置き換えたところで、Excel が残ってしまう状況は変わらないのですが、
先に紹介した URL の記事に従い、While 変換したループの後に

 'EnumeratorViewOfEnumVariant が保持している IEnumVARIANT を得る
 Dim o As Object = DirectCast(objEnum, ICustomAdapter).GetUnderlyingObject()
 If Marshal.IsComObject(o) Then 'True のはず
  '解放
  Marshal.ReleaseComObject(o)
 End If

としてみると、EXCEL.EXE が残ってしまう現象はなくなると思います。

ちなみに VB6 においても、For Each 〜 Next を使うと、Excel が正常に解放されない事があったため、
私は極力、For 〜 Next に置き換えるようにしています。



> 変更前の状態で、参照数が2以上になっていたので0になるまでRelaseComObjectを繰り返してみましたが、
> プロセスは残ったままでした。
内部的に利用された何らかの COM Object の参照が
リリースされていないのだと思います。先述の IEnumVARIANT などのように。


> これは、GCまでに時間がかかるからという理由からでしょうか。
COM のメモリ管理と .NET ベースのメモリ管理について。
http://msdn.microsoft.com/ja-jp/library/cc325771.aspx
返信 編集キー/


管理者用

- Child Tree -