Udostępnij za pośrednictwem


TN064: Apartment-Model wątkowanie w kontrolkach ActiveX

Uwaga / Notatka

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ątek Apartment-Model

Model apartamentowy to podejście do obsługi obiektów osadzonych, takich jak kontrolki ActiveX, w wielowątkowej aplikacji kontenerowej. Mimo że aplikacja może mieć wiele wątków, każde wystąpienie obiektu osadzonego zostanie przypisane do jednego "kompartmentu", który będzie wykonywany tylko w jednym wątku. Innymi słowy, wszystkie wywołania do instancji 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ątkowanie Apartment-Model

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 CCriticalSection w klasie kontrolki. Używaj funkcji składowych Lock i Unlock tego obiektu sekcji krytycznej wszędzie tam, 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 członka _strShared może być następnie chroniony przy użyciu sekcji krytycznej.

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

...
}

Rejestrowanie mieszkania -Model-Aware Control

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 kluczuInprocServer32. 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. Nie trzeba dokonywać żadnych zmian, aby zarejestrować model wątków.

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 także

Uwagi techniczne według numeru
Uwagi techniczne według kategorii