- PR -

COM参照を確実に解放するコードの可読性をあげたい

投稿者投稿内容
nanbu
大ベテラン
会議室デビュー日: 2004/08/19
投稿数: 178
投稿日時: 2006-03-16 18:23
南部です。

引用:

GC によっていつ解放されるかわからないということは、
異常終了時にはリークしたままになるということを示します。

なので「有効期間を明示的に制御する場合以外」のシナリオがあまり思いつかなかったり... (;^-^)
ユーザーに「はい、どうぞ」という意味であっても必須になるということです。


こまめにReleaseComObjectを実行していても異常終了時にリークするのは同じでは?
確率は違うでしょうけど、、、
#異常終了後のアプリケーションの安定性、、、かな?
#でも異常終了してるしな、、そこに労力をかけるべきか、、、

引用:

引用:

もし失念していなければ、これのソースを教えて欲しいのですが。


わーないです、というより多分間違ってます。
1 個というよりは未到達の分、デクリメントしようとする。
1 個でも有効な参照がある場合は、まったくデクリメントされない。
1 個だけという状況はない、が正しいかな。


ありがとうございました。
じゃんぬねっと
ぬし
会議室デビュー日: 2004/12/22
投稿数: 7811
お住まい・勤務地: 愛知県名古屋市
投稿日時: 2006-03-16 19:37
引用:

nanbuさんの書き込み (2006-03-16 18:23) より:

こまめにReleaseComObjectを実行していても異常終了時にリークするのは同じでは?
確率は違うでしょうけど、、、


そうです、参照が残っている時間が長ければ長いほど確率が増えます。
使っていないのであれば、一刻も早くプロセスごと解放したいものです。

引用:

#異常終了後のアプリケーションの安定性、、、かな?
#でも異常終了してるしな、、そこに労力をかけるべきか、、、


確かに CLR すら検知できないような異常時だけになりますから、
そう言われるとちょっと強く言えない部分はあります。(;^-^)
可読性も重視したくなる気持ちも十分に理解できます。

ファイナライザがいつ起きるかわからないというのが大きいのと、
CLR が管理しきれないのであれば、自分で管理するべきに尽きると思います。

_________________
C# と VB.NET の入門サイト
じゃんぬねっと日誌
ぼのぼの
ぬし
会議室デビュー日: 2004/09/16
投稿数: 544
投稿日時: 2006-03-16 20:12
nanbuさんのコードをちょこっとだけ改造して、動かしてみました。

コード:

private void button1_Click(object sender, System.EventArgs e)
{
    try
    {
        ExcelTest(@"C\temp\test.xls");
        lblMsg.Text = "正常終了しました。";
    }
    catch(Exception ex)
    {
        lblMsg.Text = ex.ToString();
    }
    //GC.Collect();
}

private static void ExcelTest(string outputPath)
{
    Excel.Application xlApp = new Excel.Application();
    try
    {
        xlApp.DisplayAlerts = false;
        xlApp.Visible = false;

        Excel.Workbook workbook = xlApp.Workbooks.Add(Type.Missing);
        Excel.Worksheet worksheet = (Excel.Worksheet)workbook.Worksheets["Sheet1"];

        ((Excel.Range)worksheet.Cells[1, 1]).Value2 = "COM Interop is hated!";
                
        workbook.SaveAs(
            outputPath,
            Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing,
            Excel.XlSaveAsAccessMode.xlExclusive, 
            Type.Missing, Type.Missing, Type.Missing, Type.Missing);
    }
    finally
    {
        xlApp.Quit();
    }
}


Windowsアプリケーションだと、全然問題なしですね。
タスクマネージャをのぞいてみると、ボタンを押すごとにEXCEL.EXEのプロセスが増えていきますが、
×ボタンでアプリを終了すると、全てのプロセスが消えてくれます。
GC.Collect()のコメントを外したら、ボタン押すごとにプロセスが消えるようになりました。

試しに、全く同じコードをASP.NET Webアプリケーションでも動かしてみたのですが、
なぜか1回目の実行でいきなりEXCEL.EXEが不正なメモリを参照したという赤ダイアログが出て、
その後ボタンを押してもレスポンスが帰ってこない、IISを再起動してもEXCEL.EXEのプロセスは消えず、
タスクマネージャからも殺せず、OSを再起動するハメになるという悲惨な結果に...orz

Microsoftが推奨しないのがよくわかります(^^;
nanbu
大ベテラン
会議室デビュー日: 2004/08/19
投稿数: 178
投稿日時: 2006-03-16 22:23
引用:

じゃんぬねっとさんの書き込み (2006-03-16 19:37) より:

ファイナライザがいつ起きるかわからないというのが大きいのと、
CLR が管理しきれないのであれば、自分で管理するべきに尽きると思います。


はい、もちろんアンマネージリソースの生存期間は短いに
越したことはないですね。

ただやはり可読性を考えると、オートメーションの処理 〜 GC.Correct()
の生存期間は許容範囲かなぁ、、、

引用:

ぼのぼのさんの書き込み (2006-03-16 20:12) より:

Microsoftが推奨しないのがよくわかります(^^;


、、、無念。
渋木宏明(ひどり)
ぬし
会議室デビュー日: 2004/01/14
投稿数: 1155
お住まい・勤務地: 東京
投稿日時: 2006-03-17 00:24
引用:

ただやはり可読性を考えると、オートメーションの処理 〜 GC.Correct()
の生存期間は許容範囲かなぁ、、、



それも場合によりけりです。

よく例に出てくる Excel のオートメーションの場合、「最後の参照」が解放されるまで、アウトプロセスサーバである EXCEL.exe が居残ってしまなど、様々な弊害が考えられます。

_________________
// 渋木宏明 (Hiroaki SHIBUKI)
// http://hidori.jp/
// Microsoft MVP for Visual C#
//
// @IT会議室 RSS 配信中: http://hidori.jp/rss/atmarkIT/
nanbu
大ベテラン
会議室デビュー日: 2004/08/19
投稿数: 178
投稿日時: 2006-03-19 00:38
引用:

渋木宏明(ひどり)さんの書き込み (2006-03-17 00:24) より:
引用:

ただやはり可読性を考えると、オートメーションの処理 〜 GC.Correct()
の生存期間は許容範囲かなぁ、、、



それも場合によりけりです。

よく例に出てくる Excel のオートメーションの場合、「最後の参照」が解放されるまで、アウトプロセスサーバである EXCEL.exe が居残ってしまなど、様々な弊害が考えられます。


いえ、もちろん、「最後の参照」が残っていないことが前提です。
でないとGC.Correct()する意味ないですから。

なので、
Excel.Application.Quit() 〜 ReleaseComObject()と
Excel.Application.Quit() 〜 参照解放 〜 GC.Correct()では
アウトプロセスの生存期間は大差ないです。

私が許容範囲と言ったのは、
オートメーション処理で使用したSheetやRangeのすべての参照が
参照解放 〜 GC.Correct()まで解放されないことに対してです。

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