2009-05-27 13 views
1

私はCOMオブジェクト内のイベントを処理するために匿名メソッドを使用しています。プログラムが終了すると、私が見ていたすべてのリソースに対して、最初のチャンス例外(InvalidComObjectException)が発生するという点で、私が匿名メソッドで使用しているリソースが「正しく閉じられていない」ように見えます。私はこれが大したことではないと思うが、それは「正しい」と感じていない。匿名メソッドでは、キャプチャされた変数をどのように解放/破棄/破棄しますか?

私は、匿名メソッドの範囲外のキャプチャされた変数にアクセスする方法を推測することはできません(これはあなたができないはずのものです)。アプリケーションを終了する前にリソースをクローズ/ディスポーザルするにはどうしたらよいですか?

編集:簡単な再読み込み後、私がここで何をしているのか分かりません。私は、COMオブジェクトを消費するマネージアプリケーションを作成しています。

さらに編集:私はArcGIS Engineを使ってGISデータを操作しています。この特定のケースでは、ILayerEvents_EventのVisibilityChangedイベントを使用して、GISレイヤが表示または非表示になったときを監視しています。イベントは、ブール(可視または不可視)を通過するだけで、レイヤ名ではないため、各レイヤが可視性状態の変更を作成するためにメソッドを作成する必要があります。私は動的なレイヤーを扱っているので、何とかこれを動的に行う方法が必要でした。したがって、匿名の方法です。

anonymouaメソッドの中で、(ILayerコンテキストで)外部ループからILayerEvents_Eventを取得して、どのレイヤを使用しているかを知るILayer変数があります。それは私が立ち往生しているこの時点でです。機能は機能し、アプリケーションを終了するまではすべてが壮大なので、20以上の参照はそこにぶら下がっていますが、例外はありません。

ユーザーが最後にレイヤーを表示/非表示にするのはわかりません。したがって、最後にレイヤーを無効にする方法はありません。私は何かを傷つけているようではないので、私はそれをそのまま残すことができる(または、おそらく匿名の方法よりもこれを行う良い方法がある)と思います。私は何かが足りないと思う。

+0

あなたが何かをノンストップで作業していて、最終的にそれを突破したときにあなたが気分を感じることは知っていますか?私はそこにいる。誰もが助けてくれてありがとう(Marc Gravellを含む)結局のところ、イベントにアタッチされたCOMオブジェクトと匿名メソッドのリストを保持しておき、シャットダウンする前にデリゲートの登録を解除する必要がありました。これは例外をスローせずに動作させました。 –

答えて

1

これはあなたの記述方法からは分かりませんが、C#オブジェクトへの参照を保持しているCOMオブジェクトがある可能性があります。これらのオブジェクトのメソッドは、公開されたイベントのイベントハンドラとして登録されていますCOMオブジェクトを使用していて、COMオブジェクトが使用されなくなった時点で終了します。 COMオブジェクトが "アパート"ベースであると仮定すると、これは、ファイナライザスレッドからCOMオブジェクトを作成したスレッドのWindowsメッセージキューにメッセージがポストされ、COMオブジェクトに対してReleaseが呼び出されることを要求することを意味します。その時点で、COMオブジェクトは、登録されたイベントハンドラを実装するC#オブジェクトでReleaseを呼び出す可能性が高くなります。これはアプリケーションのマネージコードの最後の実行が終了してCLRがアンロードしようとしているときに起きている可能性があります。シャットダウン中、CLRは、参照カウントがゼロになる前にオブジェクトを収集または無効状態にすることによって、可能な参照カウントリークに対処しなければならない可能性があります。だから、これは(純粋な推測)あなたが見ているものを説明するかもしれません。

この場合は、自分で選択した時点でCOMオブジェクトをシャットダウンする必要があります。解決策は、アプリケーションの通常のシャットダウンの一環として、COMオブジェクト上で0を返すまでループ内でMarshal.ReleaseComObjectを呼び出すことです。

http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.marshal.releasecomobject(VS.71).aspx

更新質問に基づいて更新、:

さて、あなたは匿名メソッドの閉鎖によって参照されるいくつかのCOMオブジェクトを持っているので。それらのCOMオブジェクトに起こる唯一のことは、Releaseが呼び出されることです。それが問題の原因になっている場合は、すでに無効な状態になっている可能性が高いです。

私は、COMオブジェクトへの参照を保持する匿名メソッドクロージャのセットを作成するときに、これらのCOMオブジェクトも別のリストに追加することをお勧めします。これにより、このシステム全体を破棄しているときにMarshal.ReleaseComObjectに電話することができます。

1

本当にしたい場合は、アプリケーション終了イベントにフックする必要があります。しかし、それよりもうまくいくのはいいと思う。

あなたは何のために匿名メソッドを使用していますか?最後に使用されたときに作業して、COMオブジェクトを処分できますか?あなたは、匿名メソッドをCOMオブジェクトを取得することができますは、すべて同じブロック内にそれらを処分する?

あなたが見ることができるように、細部に悪魔の:)

+0

私は質問の中にもう少し情報を追加しました。どんな助けも素晴らしいだろう。 –

2

は、C#で危険なモードを使用して、ヒープ上のものを作成して行われたときにそれを削除してください。別の考え方は、匿名メソッドの外にある変数にリソースへの参照を格納し、プログラムの終了時にそれらを正しく閉じることです。そしてもう一度、Dispose()を呼び出すだけです。

もう少し情報が参考になります。例外がスローされるのはいつですか?リソースとは何を意味し、「正しく閉鎖されましたか」。

+0

上記の情報を少し追加しました。参照されたオブジェクトのList <>を保持しておき、完了したらそれを処理するようなことは、順番どおりになると思いますか? –

関連する問題