2

Is it proper COM coding to initialize COM once per thread before any work is done in the thread then use as many COM calls as you wish?

For example in my worker thread I set up Volume Shadow Copy Service and also use IFileOperation and in my GUI thread I create shortcuts on the desktop using CoCreateInstance(CLSID_ShellLink...) and create Task Scheduler jobs using CoCreateInstance( CLSID_TaskScheduler...). Then for all of these operations I just call HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); once per thread upon starting the program and the threads. And of course CoUninitialize at the end.

4
  • 1
    It is not. You make a promise, cross your heart, hope to die. Providing a detail that the COM runtime cannot figure out by itself. You promise you will pump a message loop and never block the thread. You are breaking both promises. Maybe you'll get away with it, depends. You know you didn't when your program deadlocks or an event doesn't get raised. You can never be 100% sure it is safe, you don't know what other code gets injected on another machine that relies on you keeping the promise. Impossible to debug, not just because you will not be close to the machine. Commented Jun 27, 2017 at 23:53
  • Can you use simpler terms? I'm a little lost.. being a COM beginner... are you referring to using COINIT_APARTMENTTHREADED with regard to message loop? What would be the best way to do things? Commented Jun 28, 2017 at 5:42
  • Yes. Getting a message loop isn't hard to come by, you always get one from the WPF or Winforms project template. You don't have to create a window if you don't want to. Commented Jun 28, 2017 at 10:40
  • Should I be using COINIT_MULTITHREADED instead? All my COM library calls are executed in either the gui thread or the worker thread but none of the objects/calls are shared between threads - I'm just using the previously mentioned calls to VSS/IFileOperation/Task Scheduler/Shell Shortcuts. Commented Jun 28, 2017 at 19:31

1 Answer 1

3

the basics

CoInitialize(Ex) needs to be called for every thread that uses COM.

If these are "your" threads - i.e. you control their lifetime, it's customary to CoInitialize / Uninitialize at the beginning and end of the thread function.

it's not your thread

It's a bit trickier if the thread is created by someone else, and you don't know whether COM is initialized or not (e.g. when your DLL is loaded as a plugin and called via a "normal" exported function.)

There are two ways to go here:

(a) Try CoInitialize(Ex), and mark the return code.

  • S_OK means you initialized the com libraries and you need to call CoUninitialize
  • S_FALSE means COM libraries already are initialized with a compatible threading model, but you still need to call CoUninitialize (to "counter") your CoInitialue
  • An error code (FAILED(hr) == true), which usually means COM linraries were already initialized, but with a threading model that's not compatible with the one you requested. Do not call CoUninitialize if an error is returned

(b) Create your own thread
... and do all your COM work there (this might not be possible with all plugin API's)

OleInitialize vs. CoInitializeEx

Some Windows APIs may require OleInitialize which is "CoInitialize plus more".

It is not well documented which services require OleInitialize,but I've ran into problems with some Shell APIs. (Even if the main thread does OleInitialize, worker threads still use CoInitializeEx)

Sign up to request clarification or add additional context in comments.

3 Comments

Thanks peterchen. When you say at the beginning and end of the thread function - I am using Qt so I have a worker object living in a worker thread to which I can pass events that perform the code that needs to be executed in the worker thread - in my case do I initialize when the worker thread and worker object are created and uninitialize upon deletion? Or do I init/uninit just at the beginning and end of the worker object functions that use COM? So once per thread at beginning and end of lifetime or once per function executed by the thread?
Generally, once per thread, since there's some overhead for init/deinit, and having COM objects "survive" a Uninitialize/Initialize probably is undefined behavior. I'm not familiar enough with QT threading - ît's probably better to open a separate question for that.
I believe before it was enough to call CoInitialize and not having to call OleInitialize but it seems to have changed so one need to call it explicit as well. Have you noticed the same?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.