17

このようにスレッドSTAを作成すると、属性Thread.SetApartmentState(STA);でマークされたコードを実行できなくなります。[MTAThread]

[STAThread]Windowsやコンソールアプリケーションで見たことがありますが、属性を持つコードを見たことがなく[MTAThread]、どの.NETライブラリがこの属性を使用しているかわかりません。

私の質問は、MTAアパートメント状態のスレッド(自然な.NETスレッド)と比較して、アパートメント状態がSTAに設定されているスレッドの制限は何ですか?

4

2 に答える 2

18

その場合、[MTAThread]属性でマークされたコードを実行できません。

それはそれがどのように機能するかではありません。アパートタイプはスレッドのプロパティであり、メソッドのプロパティではありません。[STAThread]属性が.NETプログラムのMain()メソッドにのみ適用されていることがわかります。これは、プログラムを実行するために作成される最初のスレッドのアパートメントタイプを決定します。スレッドの実行後にSetApartmentState()を呼び出すことができないために必要です。それを超えると、属性には意味がなく、スレッドはその存続期間中STAに留まります。[MTAThread]がデフォルトであるため、表示されません。

STAであるスレッドにはいくつかの制限があります。アパートのスレッド化されたCOMオブジェクトのメソッドを呼び出そうとするコードをブロックし、多くの場合デッドロックするため、ブロックすることはできません。また、COMが別のスレッドからのメソッド呼び出しをマーシャリングできるように、メッセージループをポンピングする必要があります。マーシャリングされたメソッド呼び出しは、スレッドが「アイドル」の場合にのみ実行でき、コードの実行でビジー状態ではありません。メッセージループは、「ビジーではない」状態を提供します。

COMコンポーネントにも要件があります。標準のマーシャラーを使用できるように、自動化でサポートされているタイプのサブセットに制限することにより、マーシャリングをサポートする必要があります。または、カスタムマーシャリング用のプロキシ/スタブペアを提供します。HKCR\Interface\{iid}\ProxyStubClsid32レジストリキーは、マーシャリングの実行方法を決定します。

STAスレッドとMTAスレッド間でのアパートメントスレッドオブジェクトの共有は、明示的にサポートされています。STAスレッドはそれを作成する必要があり、MTAスレッド(または他のSTAスレッド)での呼び出しはすべてマーシャリングされます。これにより、コンポーネントは同じスレッドで行われた呼び出しのみを認識できるようになり、スレッドセーフが保証されます。追加のロックは必要ありません。

最後になりましたが、MTAスレッドでアパートメントスレッドのCOMオブジェクトを作成すると、COMは自動的にSTAスレッドを作成して、安全なホームを提供します。このための唯一の障害モードは、COMコンポーネントがマーシャリングをサポートしていない場合です。この方法で行うことの1つの欠点は、すべての呼び出しがマーシャリングされることです。それは遅いです。

于 2010-12-25T16:24:12.933 に答える
0

COMを使わなくても違いはないと思います。その場合、場合によっては、COMオブジェクトは1つまたは別のタイプのスレッドからのみアクセスできる可能性があります。COMオブジェクトが両方のアパートメントで機能する場合は、パフォーマンステストを試してください。または、MSDNでCOMアパートメントについてお読みください。しかし、それはパフォーマンスにとって重要ではないと思います。それはむしろデザインの選択か何かです。

于 2010-12-25T11:12:07.150 に答える