TN064: threading di modello di apartment nei controlli ActiveX
Nota
La seguente nota tecnica non è stata aggiornata da quando è stata inclusa per la prima volta nella documentazione online. Di conseguenza, alcune procedure e argomenti potrebbero essere non aggiornati o errati. Per le informazioni più recenti, è consigliabile cercare l'argomento di interesse nell'indice della documentazione online.
Questa nota tecnica illustra come abilitare il threading del modello apartment in un controllo ActiveX. Si noti che il threading del modello apartment è supportato solo in Visual C++ versioni 4.2 o successive.
Che cos'è il threading del modello apartment
Il modello apartment è un approccio al supporto di oggetti incorporati, ad esempio controlli ActiveX, all'interno di un'applicazione contenitore multithreading. Anche se l'applicazione può avere più thread, ogni istanza di un oggetto incorporato verrà assegnata a un "apartment", che verrà eseguito su un solo thread. In altre parole, tutte le chiamate in un'istanza di un controllo verranno eseguite nello stesso thread.
Tuttavia, istanze diverse dello stesso tipo di controllo possono essere assegnate a appartamenti diversi. Pertanto, se più istanze di un controllo condividono dati in comune (ad esempio, dati statici o globali), l'accesso a questi dati condivisi dovrà essere protetto da un oggetto di sincronizzazione, ad esempio una sezione critica.
Per informazioni dettagliate sul modello di threading apartment, vedere Processi e thread nella guida di riferimento per programmatori OLE.
Perché supportare il threading apartment-model
I controlli che supportano il threading apartment-model possono essere usati nelle applicazioni contenitore multithreading che supportano anche il modello apartment. Se non si abilita il threading del modello apartment, si limiterà il potenziale set di contenitori in cui è possibile usare il controllo.
L'abilitazione del threading del modello apartment è facile per la maggior parte dei controlli, in particolare se hanno poco o nessun dato condiviso.
Protezione dei dati condivisi
Se il controllo usa dati condivisi, ad esempio una variabile membro statica, l'accesso a tali dati deve essere protetto con una sezione critica per impedire a più thread di modificare i dati contemporaneamente. Per configurare una sezione critica per questo scopo, dichiarare una variabile membro statica della classe CCriticalSection
nella classe del controllo. Usare le Lock
funzioni membro e Unlock
di questo oggetto sezione critica ovunque il codice accesa ai dati condivisi.
Si consideri, ad esempio, una classe di controllo che deve mantenere una stringa condivisa da tutte le istanze. Questa stringa può essere mantenuta in una variabile membro statica e protetta da una sezione critica. La dichiarazione di classe del controllo conterrà quanto segue:
class CSampleCtrl : public COleControl
{
...
static CString _strShared;
static CCriticalSection _critSect;
};
L'implementazione per la classe include le definizioni per queste variabili:
int CString CSampleCtrl::_strShared;
CCriticalSection CSampleCtrl::_critSect;
L'accesso _strShared
al membro statico può quindi essere protetto dalla sezione critica:
void CSampleCtrl::SomeMethod()
{
_critSect.Lock();
if (_strShared.Empty())
_strShared = "<text>";
_critSect.Unlock();
...
}
Registrazione di un controllo compatibile con apartment-model
I controlli che supportano il threading del modello apartment devono indicare questa funzionalità nel Registro di sistema, aggiungendo il valore denominato "ThreadingModel" con il valore "Apartment" nella voce del Registro di sistema id classe nella chiave InprocServer32 della classe\. Per fare in modo che questa chiave venga registrata automaticamente per il controllo, passare il flag afxRegApartmentThreading nel sesto parametro a 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);
}
Se il progetto di controllo è stato generato da ControlWizard in Visual C++ versione 4.1 o successiva, questo flag sarà già presente nel codice. Non sono necessarie modifiche per registrare il modello di threading.
Se il progetto è stato generato da una versione precedente di ControlWizard, il codice esistente avrà un valore booleano come sesto parametro. Se il parametro esistente è TRUE, modificarlo in afxRegInsertable | afxRegApartmentThreading. Se il parametro esistente è FAL edizione Standard, modificarlo in afxRegApartmentThreading.
Se il controllo non segue le regole per il threading del modello apartment, non è necessario passare afxRegApartmentThreading in questo parametro.