这是我在几分钟前问过的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;
有人可以建议在从线程调用此函数时抛出此异常的原因吗?我确信我忽视了一些基本而简单的事情。
谢谢,邓肯
答案 0 :(得分:5)
在Execute()
方法中,您必须致电CoInitialize
和CoUnitialize
来设置和拆除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;