2

ここで助けを得るにはあまりにも具体的すぎるかもしれない問題がありますが、試してみようと思いました. UI に配置された COM オブジェクトとの ActiveX 接続を作成しました。ラッパーは AxHost を実装します。私が抱えている問題は、COM オブジェクトが存在するビューを閉じてから再度開いてみると、ログインできないことです。

私は ActiveX と COM の両方に慣れていませんが、すべてのオブジェクトを適切に閉じていないことに気付きました。私はこれを読んでいくつかの解決策を試しましたが、どれもうまくいかないようです。現在、ラッパーの Dispose メソッドをオーバーライドして、次のように接続を破棄しようとしています。

protected override void Dispose(bool disposing)
    {
        Marshal.FinalReleaseComObject(ocx);
        base.Dispose(disposing);
    }

私の知る限り、作成された COM オブジェクトは ocx だけです。ビュー クラスでは、次のように COM オブジェクトへのすべての参照を削除しようとします。

protected void FormClosing(object sender, FormClosingEventArgs e)
    {
            try
            {
                wrapper.CloseCanvasPage(canvasPageId, false);
                IsLoggedIn = !wrapper.Logout();
                wrapper.EndInit();
                wrapper.Dispose();
                wrapper = null;

                //  Garbage collect the unclosed ActiveX connections.
                GC.Collect();
                GC.WaitForPendingFinalizers();
            }
            catch (Exception ex) { }
        }
    }

ガベージ コレクションを手動で呼び出すのはよくないことだと思いますが、いくつかの投稿で、これにより迷走接続が解消されると書かれていました。うまくいかないようです。

親では、ビューで Dispose を呼び出し、それを null に設定して接続を切断しようとしましたが、まだ何かがぶら下がっています。新しい接続を作成しようとして Initialized (使用しているラッパーに含まれるプロパティ) を呼び出すと、COM オブジェクトが既に初期化されているという通知が表示されます。ただし、ログインしようとすると、初期化されていないことを示すエラー コードが表示されます。

私が犯した可能性のある明白な(またはそれほど明白ではない)間違いについて、誰か考えがありますか? 参考になる情報がありましたら、詳しく教えていただけると幸いです。

4

2 に答える 2

1

私が見る限り、オブジェクトを正しくガベージコレクションしています。私が提案できる唯一のことは、ラッパーに C++/CLI を使用することです。この方法では、COM オブジェクトに RCW (Runtime Callable Wrapper) を使用するのではなく、COM オブジェクトを直接使用します。IUnknown::Release を直接呼び出します。しかし、参照カウントが 0 になるまで (FinalReleaseComObject のように) IUnknown::Release を複数回呼び出すのが良い考えかどうかはわかりません。そうしなければならない場合は、一部のコードがオブジェクトを解放するのを忘れている (メモリ リーク) ことを意味し、FinalReleaseComObject を使用することは問題を解決する方法としては不十分です。

Initialized プロパティに何か問題がある可能性もありますが、それについては何も知りません。

于 2012-09-22T00:21:54.223 に答える