Понимание потоковых моделей в COM при программировании на Delphi - Сервер STA

ОГЛАВЛЕНИЕ

 

Правило #5:

Для того, чтобы сервер STA работал бы правильно, его поток должен включать в себя цикл, непрерывно проверяющий наличие оконных сообщений (windows messages) и, соответственно, их обрабатывающий. 

Другими словами, следующий фрагмент показывает основы реализации работающего потока STA:

var
    rMsg : TMsg;
begin
  CoInitializeEx (NIL, COINIT_APARTMENTTHREADED); >у >
  { главный цикл сообщений потока }
   while (GetMessage (rMsg, 0, 0, 0)) do
      DispatchMessage (rMsg);
   CoUninitialize;
end;

Если Вы планируете создать поток STA, не имеющий цикла обработки оконных сообщений, Вы должны учитывать, что если Вы пытаетесь получить доступ к объекту, созданному в этом STA, из других потоков (очевидно, в других STA), Ваши вызовы не будут успешно выполнены и Ваш вызывающий поток "зависнет". Очевидно, что причина происходящего кроется в том, что мы только что узнали. Я бы хотел подчеркнуть также, что цикл сообщений необходим только с той точки зрения, что Ваш поток STA собирается обслуживать объекты для потоков в других подразделениях. Действительная цель цикла обработки оконных сообщений заключается в том, что COM может выстраивать последовательно все вызовы, приходящие от всех потоков. Другими словами, если Вы собираетесь создать поток STA, который работает с объектами COM внутри того же самого потока, то нет абсолютно никакой нужды в цикле сообщений.

Например, если клиентское приложение создает поток STA и внутри этого потока создает объект COM, работает с ним и затем завершает, то нет никакого смысла в цикле сообщений вообще, т.е. 

procedure TMySTAThread.Execute;
var
  pObject1 : IObject1;
begin
  CoInitializeEx (NIL, COINIT_APARTMENTTHREADED);
  // Создает объект object1, делает с ним что-то (something) и завершается
  pObject1 := CreateOleObject ('Server.Object1') as IObject1;
  pObject1.DoSomething;
  pObject >1. >DoSomeOtherThing;
  pObject >1 := >NIL;
  // Цикл сообщений не нужен, так как мы уже все сделали
  CoUninitialize;
end ;

Очевидно, что если Вы планируете использовать модель STA в Вашем приложении, то по существу говоря это приложение является многопоточным, в котором каждый поток живет в отдельном STA. Это означает, что для COM имеется возможность делать одновременные вызовы Вашего приложения, если оно создает несколько STA (отметьте существенную разницу: для каждого STA вызовы выстраиваются последовательно, но в целом приложение может иметь несколько STA, вызовы к которым могут поступать одновременно). Это приводит нас к другому правилу, весьма важному для STA: