TN064. Потоки изолированной модели в элементах управления ActiveX

Примечание.

Следующее техническое примечание не было обновлено, поскольку сначала оно было включено в электронную документацию. В результате некоторые процедуры и разделы могут быть устаревшими или неверными. Для получения последних сведений рекомендуется выполнить поиск интересующей темы в алфавитном указателе документации в Интернете.

В этом техническом примечание объясняется, как включить потоки модели квартиры в элементе управления ActiveX. Обратите внимание, что потоки модели квартир поддерживаются только в Visual C++ версии 4.2 или более поздней версии.

Что такое потоки модели квартиры

Модель квартиры — это подход к поддержке внедренных объектов, таких как элементы управления ActiveX, в многопоточное приложение контейнера. Хотя у приложения может быть несколько потоков, каждый экземпляр внедренного объекта будет назначен одному "квартире", который будет выполняться только на одном потоке. Другими словами, все вызовы в экземпляр элемента управления будут выполняться в одном потоке.

Однако разные экземпляры одного типа управления могут быть назначены разным квартирам. Таким образом, если несколько экземпляров элемента управления совместно используют любые данные (например, статические или глобальные данные), то доступ к этим общим данным должен быть защищен объектом синхронизации, например критическим разделом.

Полные сведения о модели потоков квартиры см. в разделе "Процессы и потоки " в справочнике программиста OLE.

Почему поддерживает потоки модели квартиры

Элементы управления, поддерживающие потоки модели квартиры, можно использовать в многопоточных приложениях контейнеров, которые также поддерживают модель квартиры. Если вы не включаете потоки модели квартиры, можно ограничить потенциальный набор контейнеров, в которых можно использовать элемент управления.

Включение потоков модели квартиры легко для большинства элементов управления, особенно если у них мало общих данных или нет.

Защита общих данных

Если элемент управления использует общие данные, например статическую переменную-член, доступ к этим данным должен быть защищен критическим разделом, чтобы предотвратить изменение данных несколькими потоками одновременно. Чтобы настроить критически важный раздел для этой цели, объявите статическую переменную члена класса 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();

...
}

Регистрация элемента управления с поддержкой модели квартиры

Элементы управления, поддерживающие потоки модели квартиры, должны указывать эту возможность в реестре, добавив именованное значение ThreadingModel со значением "Apartment" в записи реестра идентификаторов класса\под ключом InprocServer32. Чтобы этот ключ автоматически регистрировался для элемента управления, передайте флаг 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);

}

Если проект элемента управления был создан controlWizard в Visual C++ версии 4.1 или более поздней, этот флаг уже будет присутствовать в коде. Для регистрации модели потоков не требуется никаких изменений.

Если проект был создан более ранней версией ControlWizard, существующий код будет иметь логическое значение в качестве шестого параметра. Если существующий параметр имеет значение TRUE, измените его на afxRegInsertable | afxRegApartmentThreading. Если существующий параметр имеет значение FALSE, измените его на afxRegApartmentThreading.

Если элемент управления не соответствует правилам потоков модели квартиры, в этом параметре не следует передавать afxRegApartmentThreading .

См. также

Технические примечания по номеру
Технические примечания по категории