この質問で説明されている問題があります: Unable to cast COM object of type exception で、エラーとして現れます:
タイプ 'System.__ComObject' の COM オブジェクトをインターフェイス タイプ 'IMyInterface' にキャストできません。IID '{GUID}' を持つインターフェイスの COM コンポーネントでの QueryInterface 呼び出しが次のエラーのために失敗したため、この操作は失敗しました: そのようなインターフェイスはサポートされていません
私の WPF アプリは、最終的に COM オブジェクトを呼び出す .NET ライブラリを呼び出しています。これは問題なく動作しますが、メイン スレッドで実行され、UI をブロックします。新しいスレッドを生成してそこからライブラリを呼び出すと、そのエラーが発生します。他の質問に関するこれらの解決策はどれも私にとってはうまくいきません。ランタイムが型情報をロードする方法を理解しようとしていますが、スレッド間で共有することはできません。
私は、WPF アプリが STA であることを理解しています。つまり、スレッド間を移動するすべてのオブジェクトが COM マーシャリングされることを知っています。「これは COM オブジェクトであり、その GUID はこれです」という型情報が AppDomain にあるのに、2 番目のスレッドにアクセスできない方法がわかりません。
ロードされた型情報はどこに存在しますか? それはAppDomainにありますか、それともスレッドごとですか? いずれにせよ、スレッドに型情報を共有させるにはどうすればよいですか? どうすればこれを修正できますか?
私はこれを読みました:
http://www.codeproject.com/Articles/9190/Understanding-The-COM-Single-Threaded-Apartment-Pa
とこれ:
http://msdn.microsoft.com/en-us/ library/ms973913.aspx#rfacomwalk_topic10
および COM 相互運用性について説明している他の多くのものを参照してください。
Hans Passant の回答に従って、2 番目の STA スレッド内にライブラリ オブジェクトを作成しています。
var thread = new Thread(delegate()
{
var aeroServer = new AeroServerWrapper(Config.ConnectionString);
var ct = new CancellationToken();
aeroServer._server.MessageReceived += ServerMessageReceived;
aeroServer.Go(@"M:\IT\Public\TestData\file.dat", ct);
});
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
イベントが発生しない場合、Application.Run() を呼び出してメッセージ キューを開始する必要があるかもしれないことは理解していますが、そこまで到達していません。COM オブジェクトを作成しようとするとすぐにクラッシュします。AeroServerWrapper は別の DLL にあり、これが 2 番目の DLL を呼び出し、最終的に COM オブジェクトのインスタンス化を試みます。
ヒントや記事をいただければ幸いです。これをそのまま解決したいと思います。私のプラン B は、コンソール アプリでライブラリをラップし、UI からコンソール アプリを生成し、名前付きパイプを介してコンソール アプリからステータス メッセージを取得することです。それはうまくいきますが、醜いようです。