tagCANDY CGI VBレスキュー(花ちゃん) の Visual Basic 2010 用 掲示板(VB.NET 掲示板)
VBレスキュー(花ちゃん) の Visual Basic 2010 用 掲示板(VB.NET 掲示板)
[ツリー表示へ]  [ワード検索]  [Home]

タイトル Re: SeriesCollection.Add後、Excelのタスクが残る
投稿日: 2020/01/27(Mon) 15:03
投稿者魔界の仮面弁士
> '確実なオブジェクト解放用
> ''' Excelオブジェクトの完全な開放

解放(Release)と開放(Open,Free)になっていますよ。


> タスクマネージャーで見るとExcelのタスク「Microsoft Excel」が残ってしまいます。

まずは解放時に、ReleaseComObject の戻り値が 0 になっていることを確認してみてください。
ReleaseComObject は、呼び出すたびに COM の参照カウントを -1 するようになっており、
参照カウントが 0 になったときに、COM オブジェクトが処分されます。

全ての解放処理で ReleaseComObject が 0 を返してくるにも関わらず、
それでも Excel が残ってしまうようであれば、ReleaseComObject に渡し忘れている
COM オブジェクトが残っている、ということを意味します。


一方、ReleaseComObject の戻り値が 1 以上になっている場合、それは
同じ COM オブジェクトへの複数の参照が生成された状態を意味します。

通常、このメソッドが 0 以外を返す状態になることは少ないのですが、
メソッドをレイトバインドで呼び出したときに、そのメソッド引数に対して
COM オブジェクトを Object 型の変数を通じて受け渡した場合、データ型判定時に
内部的な参照カウントが予期せず増大してしまうことがあり、その場合、
ReleaseComObject を 1 回呼び出しただけでは解放されないことがあります。

もしも 0 を返してこなかった場合には、ReleaseComObject の代わりに
FinalReleaseComObject を呼び出せば、そのオブジェクトの参照カウントが一気に 0 になります。



> Do Until SeriesCollectionObj.Count = 0
>     ObjRelease(srsObj) '使い回しは解放が必要。
>     srsObj = SeriesCollectionObj(1) 'コレクションは代入して消去が必要。
>     srsObj.Delete()
> Loop

順番的には

Do Until SeriesCollectionObj.Count = 0
     srsObj = SeriesCollectionObj(1)
     srsObj.Delete()
     ObjRelease(srsObj)
Loop

とするべきでは無いでしょうか?

元のコードだと、最後に取得した srsObj の中身を解放することなく、
ループ後の @ に到達してしまい、同じ変数に対して別のインスタンスへの参照が
セットされてしまい、その前に保持されていたオブジェクトの解放処理が漏れることになりそうです。



=== 以下蛇足 ===


> Option Strict Off
> Option Explicit On
>
> Dim rngObj As Range = Nothing
>
> ObjRelease(rngObj)
>
> Sub ObjRelease(ByRef obj As Object)

上記では、仮引数が As Object 、実引数が As Range となっており、
それぞれ異なるデータ型が受け渡されていることになります。

現状の「Option Strict Off」であればコンパイルは通るのですが、
その場合、メソッドの呼び出し時において
 ObjRelease(wbkObj)
という処理が
 Dim dummy As Object = wbkObj
 ObjRelease(dummy)
 wbkObj = DirectCast(dummy, Workbook)
という処理に置き換えられることになるため、無駄なやりとりが多くなります。

そこで、このようなケースでは
 Sub ObjRelease(ByRef obj As Object)
ではなく、
 Sub ObjRelease(Of T)(ByRef obj As T)
というメソッド定義に変更することをお奨めします。この方が実行効率が良いですし、
「Option Strict On」時にもそのまま使うことができます。


ちなみに、「If Not (obj Is Nothing) Then」というのは古い書き方なので、現在は
英文法的に「If obj IsNot Nothing Then」の方がスマートかと思います。

- 関連一覧ツリー をクリックするとツリー全体を一括表示します)

古いスレッドにレスはつけられません。