Serialize calls to a COM object in a single threaded model
-
Hi, I use a COM object(lot of classes and functions) that does not support the multi thread call. The program i do is multithread and then i have problem with the COM object. i would like to serialize all the calls i have to do to this object in a single thread. From the creation of the object to its release. Can someone help me please? thanks!
-
Hi, I use a COM object(lot of classes and functions) that does not support the multi thread call. The program i do is multithread and then i have problem with the COM object. i would like to serialize all the calls i have to do to this object in a single thread. From the creation of the object to its release. Can someone help me please? thanks!
If you are using ATL, try to use CComCriticalSection object. Create the data member of that type in your class and initialize it in your object's constructor. Use CComCriticalSection::Lock() and Use CComCriticalSection::Unlock() methods in code blocks that require only-one-at-a-time execution (a.k.a. serialized access or thread-safe code). This object is well documented in MSDN library. The alternative to it is Win32 API: CRITICAL_SECTION hMyCS; InitializeCriticalSection(&hMyCS); *** *** EnterCriticalSection(&hMyCS); // your thread-safe code begings *** *** *** // your thread-safe code ends LeaveCriticalSection(&hMyCS); As opposed to events, semaphores, and mutexes, critcal sections are the easiest and fastest synchronization objects. Second, events, semaphores and mutexes are mostly used for inter-process syncrhonization and communication, but you still can use them at intra-process level. When Critical Sections are used, all client threads that access your component will be automatically queued in First-Come-First-Served fashion. Windows and COM runtime will take care of that for you. Hope you find it helpful. Kirill Sherman shermank@glstrat.com
-
If you are using ATL, try to use CComCriticalSection object. Create the data member of that type in your class and initialize it in your object's constructor. Use CComCriticalSection::Lock() and Use CComCriticalSection::Unlock() methods in code blocks that require only-one-at-a-time execution (a.k.a. serialized access or thread-safe code). This object is well documented in MSDN library. The alternative to it is Win32 API: CRITICAL_SECTION hMyCS; InitializeCriticalSection(&hMyCS); *** *** EnterCriticalSection(&hMyCS); // your thread-safe code begings *** *** *** // your thread-safe code ends LeaveCriticalSection(&hMyCS); As opposed to events, semaphores, and mutexes, critcal sections are the easiest and fastest synchronization objects. Second, events, semaphores and mutexes are mostly used for inter-process syncrhonization and communication, but you still can use them at intra-process level. When Critical Sections are used, all client threads that access your component will be automatically queued in First-Come-First-Served fashion. Windows and COM runtime will take care of that for you. Hope you find it helpful. Kirill Sherman shermank@glstrat.com
All right for that, but even if the threads are queued in critical section, the critical sections are accessed by several threads, not at the same time sure! I have a class: Class CObj: public COleDispatchDriver{ public: LPDISPATCH fct1(COleVariant vrIndex); short fct2(); }; what i want is that a thread controls the access to fct1 and fct2 as a consequence, only this thread will use these functions! even if other threads call them, i want to execute these functions always in the same thread! In fact, it's a problem that i have with an ActiveX i use, its threading model is appartment, but sometime, when i access classes of the activeX with different threads, i have an error (the error is done by the activeX i use, not a window exception). Then, i thought that the best way was to create a wrapper class to the ActiveX, and this wrapper class will always work in one thread. So, all calls to the activeX are serialized. Thanks!
-
All right for that, but even if the threads are queued in critical section, the critical sections are accessed by several threads, not at the same time sure! I have a class: Class CObj: public COleDispatchDriver{ public: LPDISPATCH fct1(COleVariant vrIndex); short fct2(); }; what i want is that a thread controls the access to fct1 and fct2 as a consequence, only this thread will use these functions! even if other threads call them, i want to execute these functions always in the same thread! In fact, it's a problem that i have with an ActiveX i use, its threading model is appartment, but sometime, when i access classes of the activeX with different threads, i have an error (the error is done by the activeX i use, not a window exception). Then, i thought that the best way was to create a wrapper class to the ActiveX, and this wrapper class will always work in one thread. So, all calls to the activeX are serialized. Thanks!
That's where COM apartment may help. Your ActiveX control is apartment threaded, which means that all calls to that object always must be executed on the same thread. Looks like your client also apartment threaded, but probably when you use your ActiveX object on other thread you didn't marhsall you interface pointer (CoMarshalInterface or CoMarshalInterThread..). One possible fix, that won't require much changes, is to put all client threads in free threaded apartment (each thread should calls CoInitialiseEx(NULL, COINIT_MULTITHREADED)). There will be slight perfomance hit, since all the calls to your object will be marshalled. If it's not acceptable ( or the client must be apartment threaded), than you'll need to use CoMarshal../Unmarshall or Global interface table (see IGlobalInterfaceTable, CLSID_StdGlobalInterfaceTable) to marshal interface pointer between apartments. In this case the calls from apartment that created object won't be marshalled. Hope this helps. Edward.