从线程调用远程SOAP调用的异常

时间:2010-03-29 16:55:20

标签: web-services multithreading delphi soap

这是我在几分钟前问过的this question的扩展/下一步。

我有一个主表单和线程的Delphi应用程序。每隔X秒,线程就会对远程对象发出Web服务请求。然后它回发到主窗体,用于处理使用新信息更新UI。

我之前在我的线程中使用了TTimer对象,当TTimer回调函数运行时,它在主线程的上下文中运行(但远程Web服务请求确实有效)。这反而破坏了单独线程的目的,所以我现在在我的线程的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 个答案:

答案 0 :(得分:5)

Execute()方法中,您必须致电CoInitializeCoUnitialize来设置和拆除COM库。

您的主线程会自动在Application.Initialize()过程中执行此操作,但是,其他线程在调用COM函数之前需要调用CoInitialize

确保在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

答案 1 :(得分:2)

对于我未来的自我......我需要在我的执行方法中使用CoInitialize和CoUnInitialize:

procedure TPollingThread.Execute;
begin

  CoInitialize(nil);

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


   CoUnInitialize;
end;