Personal computing discussed

Moderators: renee, SecretSquirrel, just brew it!

 
Madman
Minister of Gerbil Affairs
Topic Author
Posts: 2317
Joined: Tue Apr 01, 2003 4:55 am
Location: Latvia

Apartment threaded COM from MTA thread

Wed Apr 21, 2010 5:01 pm

Hi, does anyone know what do I need to get the STA COM to work from a thread that calls CoInitializeEx(COINIT_MULTITHREADED);

If I CoCreate the object from CoInitializeEx(COINIT_APARTMENTTHREADED); thread, then I can query for all interface pointers and everything works fine.

But if I do the same from CoInitializeEx(COINIT_MULTITHREADED); thread, sometimes I get the IUnknown, sometimes I can even get the IDispatch, sometimes even the IMyInterface, but more often than not everything explodes with E_NOINTERFACE.

If I understand correctly that's because the COM interfaces have to be marshaled, and asking for interfaces from MTA thread this way is very wrong. But they are created via ATL wizards, and I thought the proxies should be auto-generated and the COM should take the care of all the marshaling stuff.

Am I missing something?
Core 2 Duo E6300, MSI P45 NEO-F, Club 3D GTX 260, 4Gb DDR2-800Mhz, Audigy X-Fi Fatal1ty Champ1on ed., 0.5Tb+1Tb Seagate Barracuda 7200.12, 630W AXP, Samsung SyncMaster BX2450, ViewSonic VP171b
 
Flying Fox
Gerbil God
Posts: 25690
Joined: Mon May 24, 2004 2:19 am
Contact:

Re: Apartment threaded COM from MTA thread

Thu Apr 22, 2010 8:36 am

I suppose you are talking about in-proc stuff?

In theory it should work, since CoCreating a clearly marked STA object from a free threaded apartment should be supported by COM (if you look at the thread list in the debugger, you should see 1-3 additional threads created by COM when you call CoCreateInstance to host the new STA apartment). How complex is the interface? Did you provide the custom marshaler or you stick with automation compliant data types so the default marshaler can handle for you?

Do you have control of the COM object itself? How about just switching it to free/both? I understand this may not always be possible.

The safest that I have done recently is to do it yourself: create a separate thread with COINIT_APARTMENTTHREADED, throw a message loop, and create the object there. Use that message loop for your inter-thread communication needs (hint: PostMessage should be better than SendMessage here). You need to handle the lifetime of the object in the thread, and the thread itself of course; but you will have full control without worrying about all that madness. Based on your posts I'm sure you can handle you own threads, right? ;)
The Model M is not for the faint of heart. You either like them or hate them.

Gerbils unite! Fold for UnitedGerbilNation, team 2630.
 
Madman
Minister of Gerbil Affairs
Topic Author
Posts: 2317
Joined: Tue Apr 01, 2003 4:55 am
Location: Latvia

Re: Apartment threaded COM from MTA thread

Thu Apr 22, 2010 3:58 pm

Yes, in-proc, but the component is being called from proprietary system, and it creates CoInitializeEx(COINIT_MULTITHREADED); apartment where my component has to live. As far as parameters go, I use only BSTRs, LONGs and VARIANT_BOOLs. Everything has to work with scripting stuff, so the component has dual interfaces (IDispatch), and tests from VB seem to work, always.

Concerning COM, yes, I have full control over it, but it requires some refactoring for thread safety. Also COM can fire up dialogs, so if everything I read is true, then it has to be Apartment threaded, and it has to have a message loop.

And since it's a dll, I think there will be problems if I'll create threads there. Also, I couldn't find any documentation that confirms this, but it seems that if I'll create the dll as free threaded, I won't be able to use Apartment threaded COMs from within it (containment), and also, dialogs will deadlock or crash the consumer.

The next idea was to create EXE COM, make it register as Free or Both threaded, and then create an additional thread, initialize it to STA and do the wrapping this way.

Unfortunately, the more I read the more confused I get, and each additional layer, workaround seems to bring only new problems (permissions for local server COM, deadlocks in consumer if I just change the COM to Free threaded) and so on.

I scanned through "Inside COM", read the whole relevant documentation I could find by googling, but I'm still afraid that I'll write something that will work on test system and will crash in the production environment for good because of some strange COM feature. All the time when I search for something I only get blog entries that says "Don't do that".

So right now I'm torn between trying Local server workaround and digging though custom marshaling. And I have no idea if these approaches are valid.
Core 2 Duo E6300, MSI P45 NEO-F, Club 3D GTX 260, 4Gb DDR2-800Mhz, Audigy X-Fi Fatal1ty Champ1on ed., 0.5Tb+1Tb Seagate Barracuda 7200.12, 630W AXP, Samsung SyncMaster BX2450, ViewSonic VP171b
 
Flying Fox
Gerbil God
Posts: 25690
Joined: Mon May 24, 2004 2:19 am
Contact:

Re: Apartment threaded COM from MTA thread

Thu Apr 22, 2010 5:12 pm

Madman wrote:
Concerning COM, yes, I have full control over it, but it requires some refactoring for thread safety.
Trivially it should be just adding critical sections/locks on each methods that need to access member variables.

Madman wrote:
Also COM can fire up dialogs, so if everything I read is true, then it has to be Apartment threaded, and it has to have a message loop.
Huh? Usually it is ActiveX controls or object embedding then you will get a dialog. What are you talking about? The client/host program? If it is multithreaded it shouldn't be GUI in nature...

Madman wrote:
And since it's a dll, I think there will be problems if I'll create threads there. Also, I couldn't find any documentation that confirms this, but it seems that if I'll create the dll as free threaded, I won't be able to use Apartment threaded COMs from within it (containment), and also, dialogs will deadlock or crash the consumer.
Yes, since you don't own the process spawning threads is typically bad form. However, the situation you described basically indicates that you need to implement your COM object as Both?

Madman wrote:
The next idea was to create EXE COM, make it register as Free or Both threaded, and then create an additional thread, initialize it to STA and do the wrapping this way.
Let's try not go there yet. ;)

Madman wrote:
Unfortunately, the more I read the more confused I get, and each additional layer, workaround seems to bring only new problems (permissions for local server COM, deadlocks in consumer if I just change the COM to Free threaded) and so on.
Are you sure your object is going to be used all these different ways? Usually scripting/VB is not MTA, then what is being multithreaded there on the client/host side?

Madman wrote:
I scanned through "Inside COM", read the whole relevant documentation I could find by googling, but I'm still afraid that I'll write something that will work on test system and will crash in the production environment for good because of some strange COM feature. All the time when I search for something I only get blog entries that says "Don't do that".
Sounds to me your test vs production environments are different in the sense that the production app is MT and your test app is AT? Sounds like a mess to begin with.

Madman wrote:
So right now I'm torn between trying Local server workaround and digging though custom marshaling. And I have no idea if these approaches are valid.
May need a bit more background before I can comment further. It sounds like a mess.
The Model M is not for the faint of heart. You either like them or hate them.

Gerbils unite! Fold for UnitedGerbilNation, team 2630.

Who is online

Users browsing this forum: No registered users and 1 guest
GZIP: On