TN064: model wątkowości typu apartment w kontrolkach ActiveX

Uwaga

Następująca uwaga techniczna nie została zaktualizowana, ponieważ została po raz pierwszy uwzględniona w dokumentacji online. W związku z tym niektóre procedury i tematy mogą być nieaktualne lub nieprawidłowe. Aby uzyskać najnowsze informacje, zaleca się wyszukanie interesującego tematu w indeksie dokumentacji online.

Ta uwaga techniczna wyjaśnia, jak włączyć wątki modelu apartamentowego w kontrolce ActiveX. Należy pamiętać, że wątkowanie modelu apartamentowego jest obsługiwane tylko w programie Visual C++ w wersji 4.2 lub nowszej.

Co to jest wątkowanie modelu apartamentowego

Model apartamentów to podejście do obsługi obiektów osadzonych, takich jak kontrolki ActiveX, w aplikacji kontenera wielowątkowego. Mimo że aplikacja może mieć wiele wątków, każde wystąpienie obiektu osadzonego zostanie przypisane do jednego "mieszkania", które będzie wykonywane tylko w jednym wątku. Innymi słowy, wszystkie wywołania do wystąpienia kontrolki będą wykonywane w tym samym wątku.

Jednak różne wystąpienia tego samego typu kontroli mogą być przypisane do różnych mieszkań. W związku z tym jeśli wiele wystąpień kontrolki współużytkuje dowolne dane wspólne (na przykład dane statyczne lub globalne), dostęp do tych udostępnionych danych będzie musiał być chroniony przez obiekt synchronizacji, taki jak sekcja krytyczna.

Aby uzyskać szczegółowe informacje na temat modelu wątkowania apartamentów, zobacz Procesy i wątki w dokumentacji programisty OLE.

Dlaczego warto obsługiwać wątki modelu apartamentów

Kontrolki obsługujące wątkowość modelu apartamentowego mogą być używane w wielowątkowym kontenerze, które obsługują również model apartamentów. Jeśli nie włączysz wątkowania modelu apartamentów, ograniczysz potencjalny zestaw kontenerów, w których można użyć kontrolki.

Włączanie wątków modelu apartamentowego jest łatwe w przypadku większości kontrolek, szczególnie jeśli mają niewiele lub nie mają udostępnionych danych.

Ochrona udostępnionych danych

Jeśli kontrolka używa udostępnionych danych, takich jak statyczna zmienna składowa, dostęp do tych danych powinien być chroniony za pomocą sekcji krytycznej, aby zapobiec jednoczesnemu modyfikowaniu danych przez więcej niż jeden wątek. Aby skonfigurować sekcję krytyczną w tym celu, zadeklaruj statyczną zmienną składową klasy w klasie CCriticalSection kontrolki. Lock Użyj funkcji składowych i Unlock tego obiektu sekcji krytycznej, gdzie kod uzyskuje dostęp do udostępnionych danych.

Rozważmy na przykład klasę sterowania, która musi obsługiwać ciąg współużytkowany przez wszystkie wystąpienia. Ten ciąg może być utrzymywany w statycznej zmiennej składowej i chroniony przez sekcję krytyczną. Deklaracja klasy kontrolki będzie zawierać następujące elementy:

class CSampleCtrl : public COleControl
{
...
    static CString _strShared;
    static CCriticalSection _critSect;
};

Implementacja klasy obejmuje definicje dla tych zmiennych:

int CString CSampleCtrl::_strShared;
CCriticalSection CSampleCtrl::_critSect;

Dostęp do statycznego _strShared elementu członkowskiego może być następnie chroniony przez sekcję krytyczną:

void CSampleCtrl::SomeMethod()
{
    _critSect.Lock();
if (_strShared.Empty())
    _strShared = "<text>";
    _critSect.Unlock();

...
}

Rejestrowanie kontrolki obsługującej model apartamentów

Kontrolki obsługujące wątkowość modelu apartamentów powinny wskazywać tę możliwość w rejestrze, dodając nazwaną wartość "ThreadingModel" z wartością "Apartment" we wpisie rejestru identyfikatora klasy\w kluczu InprocServer32. Aby spowodować automatyczne zarejestrowanie tego klucza dla kontrolki, przekaż flagę afxRegApartmentThreading w szóstym parametrze do 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);

}

Jeśli projekt kontrolny został wygenerowany przez kontrolkę ControlWizard w programie Visual C++ w wersji 4.1 lub nowszej, ta flaga będzie już obecna w kodzie. Do zarejestrowania modelu wątków nie są konieczne żadne zmiany.

Jeśli projekt został wygenerowany przez starszą wersję kontrolki ControlWizard, istniejący kod będzie miał wartość logiczną jako szósty parametr. Jeśli istniejący parametr ma wartość TRUE, zmień go na afxRegInsertable | afxRegApartmentThreading. Jeśli istniejący parametr ma wartość FALSE, zmień go na afxRegApartmentThreading.

Jeśli kontrolka nie jest zgodna z regułami wątkowania modelu apartamentów, nie można przekazać elementu afxRegApartmentThreading w tym parametrze.

Zobacz też

Uwagi techniczne według numerów
Uwagi techniczne według kategorii