テクニカル ノート 64: ActiveX コントロールにおけるアパートメント モデルのスレッド処理
[!メモ]
次のテクニカル ノートは、最初にオンライン ドキュメントの一部とされてから更新されていません。結果として、一部のプロシージャおよびトピックが最新でないか、不正になります。最新の情報について、オンライン ドキュメントのキーワードで関係のあるトピックを検索することをお勧めします。
このテクニカル ノートは、 ActiveX コントロールのアパートメントモデルのスレッドを有効にする方法について説明します。アパートメントモデルのスレッドが Visual C++ バージョン 4.2 以降でのみサポートされていることに注意してください。
アパートメントモデルのスレッドは何ですか。
アパートメント モデルはサポートの埋め込みオブジェクトへ方法、マルチスレッド アプリケーション内のコンテナー ActiveX コントロールなどです。アプリケーションは、複数のスレッドがあるかも知れませんが埋め込みオブジェクトの各インスタンスは、 1 文字の 「アパートメントに割り当てられ」、 1 のスレッドだけで実行されます。つまり、コントロールのインスタンスへのすべての呼び出しは同じスレッドで発生します。
ただし、コントロールの同じ型の異なるインスタンスは異なるアパートメントに割り当てることがあります。したがって、コントロールの複数のインスタンスが一般的なデータ (たとえば、静的またはグローバル データ)共有する場合、この共有データへのアクセス、クリティカル セクションなどの同期オブジェクトによって保護する必要があります。
アパートメント スレッド モデルの完全な詳細については、 OLE プログラマの手引きの プロセスおよびスレッド を参照してください。
理由アパートメントモデルのスレッドをサポートします。
バックアップ モデルのスレッドが、アパートメント モデルをサポートするマルチスレッド コンテナー アプリケーションで使用できるコントロール。アパートメントモデルのスレッドを有効にする場合は、コントロールが使用できるコンテナーの設定の可能性を制限します。
アパートメントモデルのスレッドを有効にすると、特ににほとんど共有データが存在する場合、ほとんどのコントロールに簡単です。
共有データの保護
コントロールが共有データを、静的メンバー変数など、それにアクセス使用するデータは、クリティカル セクションと複数のスレッドがデータを同時に変更されないように保護する必要があります。クリティカル セクションをこのように設定するには、コントロール クラスの CCriticalSection クラスの静的メンバー変数を宣言します。Lock を使用すると、このクリティカル セクション オブジェクトの ロック解除 のメンバー関数は常にコード共有データにアクセスします。
、すべてのインスタンスで共有される文字列を保持する必要があるたとえば、コントロール クラスを検討してください。この文字列は静的メンバー変数に保持され、クリティカル セクションを保護できます。コントロールのクラス宣言が含まれています:
class CSampleCtrl : public COleControl
{
...
static CString _strShared;
static CCriticalSection _critSect;
};
クラスの実装は、これらの変数の定義が含まれています:
int CString CSampleCtrl::_strShared;
CCriticalSection CSampleCtrl::_critSect;
_strShared の静的メンバーへのアクセスはクリティカル セクションを保護できます:
void CSampleCtrl::SomeMethod()
{
_critSect.Lock();
if (_strShared.Empty())
_strShared = "<text>";
_critSect.Unlock();
...
}
アパートメント モデルを認識するコントロールの登録
アパートメントモデルのスレッドをサポートするコントロールは、InprocServer32 の クラス ID\ キーの下のクラス ID のレジストリ エントリのアパートメント 「」の値と名前付きの値 「ThreadingModel」を追加して、レジストリでこの機能を示す必要があります。このキーを自動的にコントロールに登録します AfxOleRegisterControlClassに 6 番目のパラメーターの afxRegApartmentThreading のフラグを渡します。:
BOOL CSampleCtrl::CSampleCtrlFactory::UpdateRegistry(BOOL bRegister)
{
if (bRegister)
return AfxOleRegisterControlClass(
AfxGetInstanceHandle(),
m_clsid,
m_lpszProgID,
IDS_SAMPLE,
IDB_SAMPLE,
afxRegApartmentThreading,
_dwSampleOleMisc,
_tlid,
_wVerMajor,
_wVerMinor);
else
return AfxOleUnregisterClass(m_clsid, m_lpszProgID);
}
コントロール プロジェクトが Visual C++ バージョン 4.1 以降の ControlWizard によって生成された場合、このフラグは既にコードにあります。変更はスレッド モデルを登録する必要はありません。
プロジェクトが ControlWizard の旧バージョンによって生成される、既存のコードに 6 番目のパラメーターとして、ブール型があります。既存のパラメーターが TRUE、afxRegInsertable | afxRegApartmentThreadingに変更します。既存のパラメーターが TRUE、afxRegApartmentThreadingに変更します。
コントロールがアパートメントモデルのスレッドの規則に従わない場合、このパラメーターの afxRegApartmentThreading を渡す必要があります。