【发布时间】:2013-11-14 17:53:06
【问题描述】:
我是否需要在 Delphi 的 main/VCL 线程中调用 Coinitialize
在使用ShellExecuteEx之前?
对于线程,是的,但是对于 VCL 线程?
【问题讨论】:
我是否需要在 Delphi 的 main/VCL 线程中调用 Coinitialize
在使用ShellExecuteEx之前?
对于线程,是的,但是对于 VCL 线程?
【问题讨论】:
Windows 窗体应用程序无需致电CoInitialize。
这是在主线程中为您完成的。
更具体的TApplication.Create 在Forms.Pas:
...
if not IsLibrary then
FNeedToUninitialize := Succeeded(OleInitialize(nil));
...
【讨论】:
OleInitialize 在内部调用CoInitializeEx。
如果有疑问,那就去做吧。无论哪种情况,CoInitialize() 都会返回一个您应该检查的hr : HRESULT,因为您需要在SUCCEEDED(hr) 上使用CoUninitialize(),但在FAILED(hr) 时不需要。失败的结果通常表明它已经被调用了。
引用自您的 MSDN 参考:
尽管如此,在使用之前始终初始化 COM 是一种很好的做法 这个函数。
【讨论】:
CoInitialize 或 CoInitializeEx,包括任何返回 S_FALSE 的调用,都必须由对 CoUninitialize" 的相应调用,因此对于 CoInitialize[Ex] 的 S_OK 和 S_FALSE 结果都必须调用 CoUninitialize
SUCCEEDED()和FAILED()这样的宏/函数,你应该使用它们。而S_FALSE 是成功代码,因此SUCCEEDED(S_FALSE) 的计算结果为true。
在 RTL/VCL 源码中,COM 的初始化方式如下:
Forms.TApplication.Create 拨打OleInitialize。因此,将对所有 VCL 表单应用程序进行此调用,但不会针对服务应用程序进行调用。ComObj.InitComObj 中调用CoInitialize 或CoInitializeEx。这在ComObj 单元的initialization 部分中注册为InitProc。反过来,在您的项目 .dpr 文件代码中对 Application.Initialize 的调用将调用 ComObj.InitComObj。现在,在这些不同的 COM 初始化中,计数的是 1 和 2。在任何标准 VCL 表单应用程序中,这两者都将在启动时在主线程中运行。第 1 项首先运行,因此首先初始化 COM。这才是最重要的初始化。项目 2 运行后返回 S_FALSE 表示 COM 已经初始化。
所以,对于你的问题:
我需要在 main/VCL 线程中调用 Coinitialize 吗?
不,你没有。您可以确定 COM 已经在 VCL 应用程序的主线程中初始化。
【讨论】: