■54149 / inTopicNo.11) |
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
|
|