Web services 从线程调用远程SOAP调用时发生异常
这是我几分钟前提出的问题的扩展/下一步 我有一个带有主窗体和线程的Delphi应用程序。线程每X秒向远程对象发出一个web服务请求。然后,它将发回主窗体,主窗体处理用新信息更新UI的操作 我以前在线程中使用了TTimer对象,当TTimer回调函数运行时,它在主线程的上下文中运行(但远程web服务请求确实起作用)。这完全违背了单独线程的目的,因此我现在在线程的Execute函数中有了一个简单的循环和睡眠例程。问题是,从GetIMySOAPService()返回时引发异常 有人能告诉我们为什么从线程调用这个函数时会抛出这个异常吗?我肯定我忽略了一些基本和简单的东西Web services 从线程调用远程SOAP调用时发生异常,web-services,multithreading,delphi,soap,Web Services,Multithreading,Delphi,Soap,这是我几分钟前提出的问题的扩展/下一步 我有一个带有主窗体和线程的Delphi应用程序。线程每X秒向远程对象发出一个web服务请求。然后,它将发回主窗体,主窗体处理用新信息更新UI的操作 我以前在线程中使用了TTimer对象,当TTimer回调函数运行时,它在主线程的上下文中运行(但远程web服务请求确实起作用)。这完全违背了单独线程的目的,因此我现在在线程的Execute函数中有了一个简单的循环和睡眠例程。问题是,从GetIMySOAPService()返回时引发异常 有人能告诉我们为什么从线
谢谢,Duncan,为了我未来的自我…我需要在我的Execute方法中进行联合初始化和联合初始化:
procedure TPollingThread.Execute;
begin
CoInitialize(nil);
while not Terminated do
begin
// ...
end;
CoUnInitialize;
end;
在Execute()
方法中,必须调用CoInitialize
和CoInitialize
来设置并拆除COM库
您的主线程在Application.Initialize()
过程中自动执行此操作,但是,其他线程需要在调用COM函数之前调用CoInitialize
确保在Execute()
方法中调用CoInitialize
,而不是在构造函数中,因为构造函数是在父线程(通常是主线程)中执行的。那不是你需要的地方。它必须从您计划从中进行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;
这允许您在初始化失败时捕获错误,并确保您调用
coninitialize
您也应该发布异常类和消息。异常类为EOleException,消息为“尚未调用协同初始化”。。。这解决了我的问题,因为我认为XML引擎将需要它。执行任何与OLE相关的操作都需要调用CoInitialize()
。在OLE单元的初始化过程中,主VCL线程自己执行,对于程序员必须执行的所有其他线程,这并不直接相关,但我看到的另一个问题是,在发出终止线程的信号后,很可能会触发另一个SOAP请求。依我看,如果终止是真的,那么你不应该执行任何冗长的操作。您可以将睡眠(5000)移动到循环的底部,或者您可以使用“如果未终止,请尝试”来保护“尝试”。@Chris:True,但这仍会阻止程序终止长达5秒。简单的解决方法是在循环中调用Sleep(100)
或类似函数,并在每次迭代中检查Terminated
。另一种方法是调用SleepEx()
并在线程需要终止时将APC()排队。我还建议您阅读错误消息。它们可能包含隐藏的提示:)+1用于仅在coInitializeX()
成功时调用counInitializeX()
,以及在thread.mghie中有顶级异常处理程序,我知道我的应用程序中有一个不匹配的Co/CoUn,因为我在其中抛出了CoInitialize,因为错误就是这么说的。。。。我会在第一时间修复,但这通常是一个变更请求或升级的bug。与此同时,我将面对什么样的问题?内存泄漏,或者它会以某种方式崩溃,还是仅仅是良性的?@Chris:我不确定,我希望它是良性的,可能是一些窗口和句柄没有正确释放。尽管如此,我还是喜欢投票支持促进良好实践的答案,文档()明确指出,需要平衡调用才能优雅地关闭COM库。谢谢mghie,我会在方便的时候尽早修复,很高兴知道这可能不是太严重。
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;