TN064:ActiveX 控制項中的 Apartment Model 執行緒
注意
下列技術提示自其納入線上文件以來,未曾更新。 因此,有些程序和主題可能已過期或不正確。 如需最新資訊,建議您在線上文件索引中搜尋相關的主題。
此技術注意事項說明如何在 ActiveX 控制項中啟用 Apartment 模型執行緒。 請注意,只有 Visual C++ 4.2 版或更新版本才支援 Apartment-model 執行緒。
什麼是 Apartment 模型執行緒
Apartment 模型是支援多執行緒容器應用程式中内嵌物件的方法,例如 ActiveX 控制項。 雖然應用程式可能有多個執行緒,但内嵌物件的每個實例都會指派給一個「Apartment」,這只會在一個執行緒上執行。 換句話說,對 控制項實例的所有呼叫都會在同一個執行緒上發生。
不過,相同類型控制項的不同實例可能會指派給不同的 Apartment。 因此,如果控制項的多個實例共用一般資料(例如靜態或全域資料),則存取此共用資料必須受到同步處理物件的保護,例如重要區段。
如需 Apartment 執行緒模型的完整詳細資料,請參閱 OLE 程式設計人員參考 中的 進程和執行緒 。
為何支援 Apartment-Model 執行緒
支援 Apartment 模型執行緒的控制項可用於同時支援 Apartment 模型的多執行緒容器應用程式中。 如果您未啟用 Apartment 模型執行緒,將會限制可以使用控制項的潛在容器集。
啟用 Apartment 模型執行緒對於大多數控制項來說很容易,特別是如果它們幾乎沒有或沒有共用的資料。
保護共用資料
如果您的控制項使用共用資料,例如靜態成員變數,該資料的存取應該受到重要區段的保護,以防止一個以上的執行緒同時修改資料。 若要為此設定重要區段,請在控制項的 類別中宣告 類別的靜態成員變數 CCriticalSection
。 Lock
無論您的程式碼在何處存取共用資料,請使用這個重要區段物件的 和 Unlock
成員函式。
例如,請考慮需要維護所有實例所共用之字串的控制項類別。 此字串可以在靜態成員變數中維護,並受到重要區段的保護。 控制項的類別宣告會包含下列專案:
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();
...
}
註冊 Apartment-Model-Aware 控制項
支援 Apartment 模型執行緒的控制項應該在登錄中指出這項功能,方法是在類別識別碼 \ InprocServer32 機碼下 ,將具名值 「ThreadingModel」 加上類別識別碼登錄專案中的 「Apartment」 值。 若要讓控制項自動註冊此金鑰,請將第六個參數中的 afxRegApartmentThreading 旗標傳遞 至 AfxOleRegisterControlClass
:
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 所產生,則現有的程式碼會有布林值做為第六個參數。 如果現有的參數為 TRUE,請將它變更為 afxRegInsertable | afxRegApartmentThreading 。 如果現有的參數為 FALSE,請將它變更為 afxRegApartmentThreading 。
如果您的控制項未遵循 Apartment 模型執行緒的規則,您就不得在此參數中傳遞 afxRegApartmentThreading 。