LoginSignup
7

More than 3 years have passed since last update.

COMオブジェクトの解放のお作法 - C#(というか.NET)

Last updated at Posted at 2019-10-24

経緯

COM Objectといえば「ReleaseComObjectで解放だー」みたいな印象があるが、.NETからExcelとか操作してると、いろんなオブジェクトが参照カウント増やしてくれやがるので、管理できなくなるしtry{...}finally{解放処理}のネストがエグくなる。

そんななか

Marshal.ReleaseComObjectは危険な場合がある

というのを目にして、どうやればよいのか、
COMオブジェクト×.NETに関するKindle書籍(下記「参考書籍」参照)を持ってたので少し調べてみた。

参考書籍

.NET and COM: The Complete Interoperability Guide - Adam Nathan著

著者はMicrosoftの中の人のよう。

読破できる気がしないので、書籍内検索する形で活用。

GCに任せる方法

6章Advanced Topics for Using COM Components の Listing 6.5 とその前のあたりの記載より。

GCに任せるという手法が紹介されている。(推奨なのかどうかは読解できず。)

(まんま載せると著作権的によくなさそうなので雰囲気だけ。)

using System.Runtime.CompilerServices;

[MethodImpl(MethodImplOptions.NoInlining)]
static void WorkWithMsOfficeComponent()
{
    XXX(Excelとか).Application app = new XXX.Application();
    ...
    app.Quit();
}

static void Main()
{
    WorkWithMsOfficeComponent();
    GC.Collect();
    GC.WaitForPendingFinalizers();
}

スコープ(変数の生存区間)の短いauto変数に押し込めることができるなら、上記のやりかたが楽っぽい。

属性 [MethodImpl(MethodImplOptions.NoInlining)] を指定しているのは、JIT1によるインライン展開を防止してGCを意図通りに機能させるため。

参考サイト

計測方法とかが参考になりそう。(時間なくてまだ試せていないです。)
.NETを使ったOfficeの自動化が面倒なはずがない―そう考えていた時期が俺にもありました。


  1. JIT(Just in time)コンパイラ(実行時にNativeな実行プログラムにコンパイルされる)によってインライン展開されると、変数の生存区間がプログラマの意図通りにならず、結果としてGCがプログラマの意図通りに動作しない。 

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7