問題タブ [apartments]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
c++ - Com Threading/Apartment の動作が整列化されたファクトリと一致しない
CoRegisterClassObject を使用して、com オブジェクトを含む dll をロードする方法をカスタマイズしようとしています。スレッドのアパートメント タイプが com オブジェクトのものと一致しないときに発生していた問題を解決する方法を試しています。基本的な考え方は、coregisterclassobject を使用すると com オブジェクトの作成時にレジストリが無視されるため、STA オブジェクトが STA スレッドで作成されていることを確認する必要があり、MTA オブジェクトについても同様であるということです。これは、常に期待どおりに動作するとは限らない概念実証として作成したサンプルです。
そして、これが私の主な機能の関連部分です。
CoRegisterClassObject でレジストリを使用するべきではないため、現在の MTA スレッドではなく STA でアパートメント スレッド オブジェクトを手動で作成する必要があり、その逆も同様であるという考えでした。CoRegisterClassObject を使用していない場合、CoGetClassObject は新しいスレッドを生成し、そのスレッドで DllGetClassObject を呼び出すことに気付きました。そのため、クラス ファクトリを STA で作成するだけで、オブジェクトがそこに存在することがわかりました。
私が見ている問題は、上記の例では、スレッド ID が常に期待どおりに表示されるとは限らないことです。FactoryThread がアパートメント スレッドとして初期化され、メイン スレッドがマルチスレッドとして初期化されている場合、期待どおりに THREAD_ID_2 == THREAD_ID_3 == THREAD_ID_4 != THREAD_ID_1 になります (ファクトリはこれらのオブジェクトを作成しており、ファクトリのスレッドに存在できます)。ただし、これらのスレッド モデルが切り替えられると、thread_id_3 == thread_id_4 になりますが、com オブジェクトはスレッド 2 で作成できますが、thread_id_2 および thread_id_1 とは異なります。
これは一貫性がないように思われ、別のスレッドが関与している状況では望ましくない動作を引き起こす可能性があります。レジストリのみに依存し、coregisterclassobject を使用しない場合、STA でフリースレッド オブジェクトを作成すると、そのオブジェクトは、MTA にある com によって生成された別のスレッドで作成されます。も STA にあり、そこでオブジェクトを作成すると、新しいスレッドではなく、com によって生成された最初の MTA スレッドに配置されます (オブジェクトの threadingmodel とスレッドのアパートメント タイプが逆の場合も同様です)。ただし、上記のように coregisterclassobject を使用して独自のファクトリを作成し、オブジェクトがマルチスレッド化されていてスレッドが STA にある場合、これらのマルチスレッド化オブジェクトを作成した新しいスレッドごとに新しい MTA スレッドが生成されます。
.net - COM+ 長時間実行メソッドにより、他のメソッドがブロックまたはハングする
別のスレッドからキャンセルできるようにする必要がある、実行時間の長い COM+ メソッドがあります。COM+ オブジェクトを操作するために C#/.NET を使用しています。両方の COM+ オブジェクトを「フリー」スレッド モデルを持つように構成しました。この C# サンプルは、COM+ オブジェクトの使用方法を示しています。
私の長期実行プロセスはキャンセル トークンを正しくチェックして、処理を終了する必要があるかどうかを判断しますが、Cancel
メソッドは COM+ オブジェクトに到達しません。メソッドがブロックされているかのように、LongProcess
終了を待っています。「フリー」スレッド モデルにより、実装が同期を管理できると考えたため、なぜこれを行っているのかわかりません。
これは、再現する最小限の例を含む BitBucket リポジトリです。 https://bitbucket.org/theonlylawislove/so-blocking-com-call
Cancel
が呼び出されない/ブロックされないのはなぜですか?
COMオブジェクトのキャンセル
サンプルCOMオブジェクト
c# - C# スレッド間の COM オブジェクトのマーシャリング
C# がスレッド間で COM オブジェクトをマーシャリングするかどうかについて非常に混乱しています。この目的のために、一連のファイルをタスク並列方式でロードするアプリケーションがあります。COM オブジェクトを使用してファイルをロードするためにStaTaskScehdulerを使用しています。COM オブジェクトが読み込まれたら、オブジェクトを中央のリストに格納します。
その後、再び STATaskScheduler を使用して、このデータに対して何らかの処理を実行しようとします。しかし、この時点で私は問題にぶつかりました。次のように例外を受け取ります。
オブジェクトが新しいスレッドにマーシャリングされていないため、このエラーが発生することがわかりました。これはC#があなたのために行うものだと思いましたか?
あるスレッドでアパートメント スレッド COM オブジェクトを作成し、それを別のスレッドから使用するにはどうすればよいですか?
ここで間違ったツリーを吠えていますか? スレッドに Sta アパートメントを使用するべきではありませんか? オブジェクトが複数のスレッドから同時にアクセスされることは決してないことを保証できます。どんな考えでも大歓迎です。
編集:COMオブジェクトは次のように定義されています:
私の理解では、これはアパートメントスレッドオブジェクトですよね?アパートメントの状態を設定しない変更されたタスク スケジューラを使用してみました (既定では MTA ですか?)。このオブジェクトは、あるスレッドで作成して別のスレッドから使用すると機能するようです。これは安全ですか、それとも別の方法で私を噛むために戻ってきますか?
COM のスレッディング モデルは、私をいつも混乱させてきました :/
c# - WinForms スレッドで CoInitializeEx を使用する
次の手順を持つDSLRカメラ用のSDKを使用しています。
Windowsアプリケーション開発時の注意事項 Windowsで動作するアプリケーションを作成する場合、メインスレッド以外のスレッドからカメラにアクセスするため、スレッドごとにCOMの初期化が必要です。ユーザー スレッドを作成し、そのスレッドからカメラにアクセスするには、必ずスレッドの開始時に CoInitializeEx( NULL, COINIT_APARTMENTTHREADED ) を実行し、最後に CoUnInitialize() を実行してください。サンプルコードを以下に示します。これは、EdsCameraRef だけでなく、別のスレッドから EdsVolumeRef または EdsDirectoryItemRef オブジェクトを制御する場合も同じです。
私のアプリケーションは C# WinForms アプリで、通常はマネージ スレッド クラスと Control.Invoke 関数を使用してクロススレッドの問題を回避しています。
私は SDK を使用するための C# のサンプル ソース コードを持っていないので、私の質問は、属性CoInitializeEx
でマークされたアプリで使用するのに役立つか、または使用する必要があるかということです。[STAThread]
アプリでスレッド用の新しいアパートメントを作成する必要があるというシナリオに遭遇したことはないので、スレッド モデルをよりよく理解するのに役立つ洞察が得られます。
更新:アパートと COM についてもう少し読んだ後、ある程度の意味を持ち始めています。ここで、.NET マネージ スレッド クラスの既定値が何になるのか疑問に思っています。また、P/Invoke を使用せずに、各スレッドに管理された方法でアパートメント モデルを指定できますか?
visual-studio - 既存のVisual Studio C++プロジェクトでアパートモデルを変更するには?
COM ウィザードを使用して作成された Visual C++ 2013 プロジェクトがあります。このコンポーネントを作成するとき、アパートメント モデルが選択されました。プロジェクトを最初から作り直すことなく、このモデルを別のアパートに変更する方法はありますか?