Исключение, вызывающее удаленный вызов SOAP из потока - PullRequest
4 голосов
/ 29 марта 2010

Это расширение / следующий шаг этого вопроса Я задавал несколько минут назад.

У меня есть приложение Delphi с основной формой и потоком. Каждые X секунд поток выполняет запрос веб-служб для удаленного объекта. Затем он отправляет обратно в основную форму, которая обрабатывает обновление пользовательского интерфейса с новой информацией.

Ранее я использовал объект TTimer в своем потоке, и, когда выполнялась функция обратного вызова TTimer, она выполнялась в контексте основного потока (но запрос удаленных веб-служб работал). Это скорее побеждало назначение отдельного потока, и теперь у меня есть простая процедура loop и sleep в функции Execute моего потока. Проблема в том, что при возврате из GetIMySOAPService () выдается исключение.

procedure TPollingThread.Execute;
var
SystemStatus : TCWRSystemStatus;
begin
while not Terminated  do
begin
  sleep(5000);
  try
    SystemStatus := GetIMySOAPService().GetSystemStatus;
    PostMessage( ParentHandle, Integer(apiSystemStatus), Integer(SystemStatus), 0 );
    SystemStatus.DataContext := nil;
    LParam(SystemStatus) := 0;
  except
  end;
end;
end;

Может кто-нибудь посоветовать, почему возникает это исключение при вызове этой функции из потока? Я уверен, что пропускаю что-то фундаментальное и простое.

Спасибо, Дункан

Ответы [ 2 ]

5 голосов
/ 30 марта 2010

В вашем методе Execute() вы должны вызвать CoInitialize и CoUnitialize для настройки и демонтажа библиотеки COM.

Ваш основной поток автоматически делает это в процедуре Application.Initialize(), однако другие потоки требуют вызова CoInitialize перед вызовом функций COM.

Убедитесь, что вы вызываете CoInitialize в методе Execute(), а не в конструкторе, потому что конструктор выполняется в родительском потоке (обычно в основном потоке). Это не там, где вам это нужно. Он должен вызываться из потока, из которого вы планируете делать вызовы COM.

Я рекомендую использовать этот формат:

try
  // OleCheck will raise an error if the call fails
  OleCheck(CoInitializeEx(NIL, COINIT_MULTITHREADED or COINIT_SPEED_OVER_MEMORY));
  try
    // Do work here
  finally
    CoUninitialize;
  end;
except
  // We failed, do something
end;

Это позволяет вам перехватить ошибку, если она не инициализируется, и гарантирует, что вы вызываете CoUninitialize.

2 голосов
/ 29 марта 2010

Для моего будущего я ... Мне нужно было CoInitialize и CoUnInitialize в моем методе Execute:

procedure TPollingThread.Execute;
begin

  CoInitialize(nil);

  while not Terminated  do
  begin
  // ...
  end;


   CoUnInitialize;
end;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...