На этом шаге мы рассмотрим особенности создания апартаментов.
Каким же образом клиенты и серверы СОМ могут создавать апартаменты в соответствии со своими требованиями? Для этого они должны соблюдать одно правило: каждый поток, который желает использовать СОМ, должен создать апартамент путем вызова функции CoInitializeEx. Она объявлена в модуле ActiveX.pas следующим образом:
const COINIT_MULTITHREADED = 0; СОINIT_APARTMENTTHREADED = 2; COINIT_DISABLE_OLEIDDE = 4; COINIT_SPEED_OVER_MEMORY = 8; function CoInitializeEx (pvReserved: Pointer; coInit: Longint): HResult; stdcall;
Параметр pvReserved зарезервирован для будущего использования и должен быть равен nil, а параметр coInit определяет модель потоков создаваемого апартамента. Он представляет собой комбинацию из следующих флагов:
Функция возвращает значение S_OK в случае успешного создания апартамента.
По завершении работы с СОМ (или перед завершением работы) поток должен уничтожить апартамент путем вызова процедуры CoUninitialize, также описанной в модуле ActiveX:
procedure CoUninitialize; stdcall;
Каждому вызову CoInitializeEx должен соответствовать вызов CoUninitialize, то есть если вы используете СОМ в приложении, вы должны вызвать процедуру CoInitializeEx до первого вызова функций СОМ и CoUninitialize перед завершением работы приложения. Библиотека VCL выполняет автоматическую инициализацию СОМ при использовании модуля ComObj. По умолчанию создается STA. Если вы хотите задействовать другую модель потоков, следует установить флаг инициализации СОМ до оператора Application.Initialize:
program Project1; uses Forms, ComObj, ActiveX, Unit1 in 'Unit1.pas' {Form1}; {$R *.RES} begin CoInitFlags := COINIT_MULTITHREADED; Application.Initialize: Application.CreateForm(Form1, Form1); Application.Run; end.
Если COM используется в потоке, то эти функции должны быть вызваны в методе Execute:
procedure TMyThread.Execute; begin CoInitializeEx (nil, COINIT_MULTITHREADED); . . . CoUninitialize; end;
На следующем шаге мы закончим изучение этого вопроса.