2017-06-27 64 views
1

在线程完成任何工作之前,每个线程初始化COM一次COM编码是否正确,然后根据需要使用尽可能多的COM调用?为多个COM操作初始化COM

举例来说,在我的工作线程我成立卷影复制服务,还可以使用IFileOperation,在我的GUI线程使用我的CoCreateInstance(CLSID_ShellLink...)桌面上创建快捷方式,并使用CoCreateInstance(CLSID_TaskScheduler...)创建任务计划程序作业。然后,对于所有这些操作,我只需在启动程序和线程时每个线程调用HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);一次。最后还有CoUninitialize。

+1

它不是。你做出承诺*,交叉你的心,希望死亡。提供COM运行时自身无法弄清楚的细节。你保证你会抽出一个消息循环并且不会阻塞线程。你违背了两个承诺。也许你会摆脱它,取决于。你知道你没有当你的程序死锁或事件没有得到提升。你永远无法100%确定它是安全的,你不知道其他代码在另一台依赖于你遵守诺言的机器上注入了什么。不可能调试,不仅仅是因为你不会接近机器。 –

+0

你可以使用更简单的条款吗?我有点迷路..作为一个COM初学者......你是指在消息循环方面使用COINIT_APARTMENTTHREADED?什么是做事的最佳方式? –

+0

是的。获取消息循环并非难事,你总是从WPF或Winforms项目模板中获得一个。如果你不想要,你不必创建一个窗口。 –

回答

2

CoInitialize(Ex)需要的基本知识被要求使用COM每个线程。

如果这些是“您的”线程 - 即您控制了它们的生命周期,则通常在线程函数的开始和结束处使用CoInitialize/Uninitialize。

这不是你的线程

这是一个有点棘手,如果线程是由其他人创建的,而你不知道COM是否已初始化与否(例如,当您的DLL加载插件和通过一个“正常”的导出函数调用)

有两种方法可以去这里:

(一)尝试CoInitialize的(防爆),并标出返回代码。

  • S_OK意味着你初始化COM库,你需要调用CoUninitialize
  • S_FALSE意味着COM库已被初始化与兼容的线程模型,但你仍然需要CoUninitialize调用(以“反”)的CoInitalue
  • 错误代码(FAILED(hr) == true),这通常意味着COM库已经初始化,但是线程模型与您请求的线程模型不兼容。难道调用CoUninitialize如果返回错误

(二)创建您自己的线程
......并且把你所有的COM工作存在(这可能无法与所有插件API的)

OleInitialize与CoInitializeEx的

一些Windows的API可能需要OleInitialize这是 “CoInitialize的还有更多。”

没有很好的记录哪些服务需要OleInitialize,但是我遇到了一些Shell API的问题。 (即使主线程确实OleInitialize,工作线程仍然使用CoInitializeEx

+0

谢谢peterchen。当你在线程函数的开始和结尾说 - 我使用Qt,所以我有一个工作对象生活在一个工作线程中,我可以传递执行需要在工作线程中执行的代码的事件 - 在我的大小写的情况下,当工作线程和工作对象被创建并且在删除时未初始化时,我是否需要初始化?或者,我只是在使用COM的worker对象函数的开头和结尾处初始化/取消初始化?那么每个线程在生命周期的开始和结束时或者线程执行的每个函数执行一次? –

+0

通常,每个线程一次,因为init/deinit有一些开销,并且让COM对象“生存”,Uninitialize/Initialize可能是未定义的行为。我对QT线程不够熟悉 - 可能最好为此打开一个单独的问题。 – peterchen

+0

我相信在调用CoInitialize之前就已经足够了,而不必调用OleInitialize,但它似乎已经发生了变化,所以也需要明确地调用它。你注意到了吗? –