Does WaitForMultipleObjects cause problems in a thread creating STA COM objects? - c++

I have a thread which creates COM objects that use the STA model.
This thread's Run function puts it in an infinite WaitForMultipleObjects.
Is it possible that the infinite WaitForMultipleObjects could prevent other threads from marshaling calls to the COM objects owned by this thread?
Basically, I'm asking if WaitForMultipleObjects would prevent the hidden COM message queue from being pumped.

Yes, problems are possible - see this KB article. Basically if your thread is an STA thread it should not call functions that can block for long periods of time since while the thread is blocked it doesn't pump and dispatch messages and this can prevent proper marshalling functioning.

Related

Why shouldn't gui threads live in multithreaded apartments?

The COINIT - an enumeration used to specify whether a windows thread is in a single or multithreaded apartment - documentation (http://msdn.microsoft.com/en-gb/library/windows/desktop/ms678505(v=vs.85).aspx) states that:
The multi-threaded apartment is intended for use by non-GUI threads. Threads in multi-threaded apartments should not perform UI actions. This is because UI threads require a message pump, and COM does not pump messages for threads in a multi-threaded apartment.
Why shouldn't threads in multi threaded apartments perform UI actions? What is wrong with having a message loop in a thread in a multi threaded apartment? Does COM somehow provide an automatic message loop for a thread in a single threaded apartment?
That's a bit backwards, a UI thread primarily requires a message loop so that it can receive notifications from Windows and other processes. A message loop is the universal solution to the producer-consumer problem. With the operating system and other processes producing, the UI thread consuming.
A UI thread uses lots and lots of code that is not thread-safe. This includes major features implemented in COM, like drag+drop, the clipboard, the shell dialogs, ActiveX controls like a browser. And a raft of code that was never made thread-safe because the programmer didn't have to make it so, much easier to write. Those features require an STA thread, in other words a thread that initializes COM by passing COINIT_APARTMENTTHREADED to CoInitializeEx().
That is a promise to COM that the thread will be a good citizen, it is not allowed to make blocking calls and must pump a message loop. It is the message loop that COM uses to marshal a call from a worker thread to the STA thread in order to keep a COM object thread-safe. When all the calls are made from the same thread then there's never a safety issue. The underlying call is SendMessage(), with a ton of plumbing to copy the function arguments from one stack to another. CoInitializeEx() creates a hidden message window owned by the STA thread that processes the message and actually makes the call. Safely.

When exactly does a non main GUI thread exit in Windows?

Say the main window of a GUI application creates a helper UI thread and the application closes. When and where will the application get a chance to clean up the thread resources? I know that the system automatically clears the resources but that doesn't help application specific resources like files etc.
As a test I had written MessageBox() in the destructors of window objects but they are not called from within the helper threads on closing the application.
It seems the systems simply shuts down the threads, may be via internal TerminateThread or some such call. Is there a way to know when exactly a thread with UI terminates and trap it?
I am using Win32 API not MFC etc.
Pseudocode
OnCreateHelperUI() // called from WndProc under appropriate message
CreateThread(...,UIThread,...)
return
UIThread()
Some auto objects on stack
Some dynamic objects on heap
CreateWindow()
while(GetMessage()){}
delete heap objects
return 0
The destructors of auto and heap objects aren't called.
FYI, waiting on the thread handle doesn't help. It simply lets the threads stick around forcing the user to close them individually. CloseHandle() will lead back to square one.
The thread closes when the thread function returns. The OS cannot do that for you, you must design it in. One good way is to have your main thread WM_CLOSE handler send a signal or message to the secondary thread. The secondary thread cleanly cleans up and returns (running destructors). While this is happening the main thread should be waiting on the thread handle, so it does not shut the app down until the secondary thread has shut down.

How to end _beginthreadex()?

Inside my desktop application I have created a simple thread by using _beginthreadex(...). I wonder what happens if my application will be closed (without explicitly closing the thread)? Will all resources inside the thread be cleared automatically? I have doubts.
So I like to end the thread when my application will be closed. I wonder what would be the best practise?
Using _endthreadex is only possible inside(!) the thread and something like TerminateThread(...) does not seems to work (infinite loop). Do you have some advices?
When main exits your other threads will be destroyed.
It's best to have main wait on your other threads, using their handles, and send them a message (using an event, perhaps) to signal them to exit. Main can then signal the event and wait for the other threads to complete what they were doing and exit cleanly. Of course this requires that the threads check the event periodically to see if they need to exit.
When the main thread exits, the app and all of its resources are cleaned up. This will include other threads and their resources.
Also, post the code you have for TerminateThread, because it works.
The tidiest way is to send your thread(s) a message (or otherwise indicate via an event) that the tread should terminate and allow it to free its resources and exit its entry point function.
To close the thread, you need to call CloseHandle() with the handle returned by _beginthreadex.
The thread is part of the process, so when the process terminates it will take the thread with it and the operating system will resume ownership of everything the two own, so all the resources will be released.
Bear in mind that if you have not forewarned the thread that the-end-is-nigh, it may be in the middle of some work when it ends. If it is in the middle of using any system or external resources, they will be released but may be in a funky state (e.g. a file may be partially written, etc).
See also http://www.bogotobogo.com/cplusplus/multithreading_win32A.php
Note: Using CloseHandle() is only for _beginthreadex and not if you are using _beginthread. See http://msdn.microsoft.com/en-us/library/kdzttdcb(v=vs.90).aspx

STA (Single Threaded Apartment) COM Object - Spawn worker threads?

Is it a bad thing to spawn worker threads in your STA COM object (ie. COM object creates a thread to perform a task)? I think, the answer is - that depends!
For example in my case:
The worker threads that I am using will not interfere/access COM or COM Services.
Reason why I am asking this is because by STA COM definition STA can only house one thread. Spawning multiple threads kind of goes against this principle unless the worker threads and the work they do NOT interfere/deal with COM/COM services.
In this case I am thinking this is perfectly fine and in my opinion the worker threads should not be considered by COM as part of the logical STA.
What are your thoughts on this?
No, that's not a bad thing. Apartments explicitly exist to help you getting multi-threaded code working. An STA thread is a safe home for a COM server that's not thread-safe, COM's apartment threading model ensures that it is always used in a thread-safe way. All you have to do is the marshal the interface pointer you want to use in the worker thread (IGlobalInterfaceTable for example) and you can call the methods without doing anything special.
This doesn't come for free of course, there's overhead involved in marshaling the call. How much depends on how responsive the STA thread is when it pumps its message loop. If you intended to create the worker thread explicitly to use that COM server in a multi-threaded way then of course you'll not be ahead, you made it slower.
Don't let the worker threads use COM in any way, and you should be fine. This means you can't call COM objects in the worker and you can't call COM runtime APIs from the worker... either directly or indirectly.
The important thing to realize is that any new threads you create are new threads in their own right; it actually doesn't matter at all which thread created them. The two things that matter are: (1) that those new threads themselves call CoInitializeEx and either get their own STA each, or share an MTA together, and (2) any COM object pointers you transfer between threads get marshaled appropriately. Do not ever just pass a COM object pointer from one thread to another in a global variable; instead use the GIT or CoMarshalInterThreadInterfaceInStream as appropriate.
(One exception to this: you can pass COM pointers freely between MTA threads; but only once that pointer has been appropriately marshaled into the MTA in the first place.)
Also, you need to be very aware of there objects live and what their affinities are. If you create an object on a STA thread, and marshal a pointer to another thread, then the typical case is that the object will still live on that original STA thread with calls returning to that thread, unless you takes specific steps to specify otherwise. (Things to watch for here: what the object's threading model is, and whether it 'aggregates the free-threaded marshaller'.)
So it's not a bad thing; but be sure that you do it appropriately. For example, you might think that using two threads might be more efficient; but then later on realize that a lot of time is being spent by that worker thread calling back to the object on the original thread, giving you worse performance than a single-threaded case. So you need to think out your threads and object strategy carefully first.
(Having said all of that, you can of course spin up as many threads as you want that don't call CoInitialize, so long as they don't use COM or COM objects in any way; if those threads to need so somehow communicate with the threads that do use COM, it's up to you to manage that communication using any 'classic' IPC mechanism of your choice - eg. messages, globals, etc.)

Asynchronous COM C++ calls

Following up from part of this question, what is the best way to have a worker thread that invokes a COM procedure in a DLL, to do this asynchronously so that the worker thread is not blocked on this call?
Note that a call to this COM DLL can take a long time as it will do DB accesses and possible run long running queries.
I wondered if asynch is possible in this scenario or if one has to just wait for the call to complete?
Take a look at this article:
http://msdn.microsoft.com/en-us/magazine/cc301334.aspx
You can also do it by yourself: create another thread for COM calls, and pass information from your worker thread to it somehow - for instance, using a queue of command pattern objects.
http://en.wikipedia.org/wiki/Command_pattern
This is, in general, not possible. COM takes care of the threading requirements for a COM server. Which it advertises in the registry. Have a look-see with Regedit.exe and locate the HKCR\CLSID{guid} key for the coclass that you use. The ThreadingModel key says what is required.
If it is missing or set to Apartment then the server says that it needs to be created on an STA thread and its interface methods must be called from that same thread. If you call a method from another thread then the call gets marshaled to the STA thread. That's safe but it is slow and you don't have any concurrency.
If it is set to Both then the call is still marshaled when the COM object was created on an STA thread. But not when it was created on an MTA thread. Only Free allows free threading. Which is very rare, the vast majority of COM components are apartment threaded and don't have the internal protection that's required to make calls from a worker thread.
There's typically only one STA thread in a program, the startup thread. It must pump a message loop, a hard requirement for STA. If you don't have one, COM will create an STA thread for you to find a good home for the server. All calls will be marshaled then.
Not good news, I'm sure, there's no free lunch in threading.