COM Threading Models for ActiveX Applications
COM threading is one aspect of ActiveX programming that can be difficult to understand. This section is a brief high-level introduction to this topic. If you are an advanced user, refer to www.msdn.com.
Every ActiveX server notifies the Windows COM run-time layer about its threading restrictions, whether it can be accessed concurrently from multiple threads, if so, what kind of threads can access it, and so on. These restrictions are referred to as the threading model of the server. You must satisfy the restrictions imposed by the published threading model of the server. For the most part, threading model restrictions apply to thread protection of the server’s global and object data when the data are accessed by multiple threads. For this reason, NI recommends that you use the Set/Get/Release Server/Object Data functions in the LabWindows/CVI ActiveX Library to protect your server and object data. A DLL ActiveX server publishes its threading model by registering it in the system registry. An ActiveX server executable publishes its threading model by calling a system function when it is run. For servers built in LabWindows/CVI, the LabWindows/CVI ActiveX Library and the generated code handle these tasks automatically.
In the following threading model tables, all references to the creation and access of objects refer to the creation and access from the ActiveX server perspective. For example, consider a situation in which a client uses three different threads to create and access three different objects implemented by a single-threaded server. To the server, all objects in the server are created and accessed in a single thread. This is the intended perspective when stating that “All objects in the server are created and accessed in a single thread”.
COM Threading Models for EXE Servers
The following table displays the COM threading models for EXE servers offered by the LabWindows/CVI ActiveX Library.
Model | Object Creation | Data Protection (Thread Safety) | Operating Systems | Comments |
---|---|---|---|---|
Single Threaded | All objects in the server are created and accessed through a single thread. | You do not need to protect or per-object data. | All versions of Windows. | The main thread must process message by calling RunUserInterface, ProcessSystemEvents, or GetUserEvent. |
Multithreaded | Objects can be created and accessed by any number of threads simultaneously. | Both global and object data must be protected. | All versions of Windows. | Threads that create user interface objects must process Windows messages so that the user interface is responsive. Because multithreaded objects are created by Remote Procedure Call (COM-RPC) threads that do not process messages, you must not use the multithreaded model for a server that contains components with a user interface. |
COM Threading Models for DLL Servers
The following table displays the COM threading models for DLL servers offered by the LabWindows/CVI ActiveX Library.
Model | Object Creation | Data Protection (Thread Safety) | Operating Systems | Comments |
---|---|---|---|---|
Single Threaded | All objects in the server are created and accessed through a single thread. | You do not need to protect or per-object data. | All versions of Windows. | The Single Threaded model's performance is not optimal if a client accesses one or more object instances simultaneously from different threads. |
Apartment Threaded | Objects can be created in multiple threads. However each object is accessed only by the thread in which it was created. | Global data must be protected. | All versions of Windows. | You must use the Apartment Threaded model or the Single Threaded model for components with a user interface. For performance reasons, use the Apartment model. |
Neutral Threaded | Objects can be created and accessed by multiple threads. Any number of threads can call into an object at the same time. | Both global and object data must be protected. | Windows 2000 and later. On earlier version of Windows, the LabWindows/CVI ActiveX Library treats this threading model as Both with Free Threaded Marshaller (FTM). | The Neutral Threaded model is the preferred model for components that are not part of the user interface. Because this threading model is treated as Both with FTM on systems earlier than Windows 2000, the server also should satisfy any restrictions imposed by the Both with FTM threading model. |
Free Threaded, Both Threaded, and Both with Free Threaded Marshaller (FTM) | Objects can be created and accessed by multiple threads simultaneously. | Both global and object data must be protected. | All versions of Windows. | Refer to www.msdn.com for more information about these threading models. Both with FTM is the recommended model for components that are not part of the user interface on versions of Windows that do not support the Neutral Threaded model. In the Both with FTM model, if the server holds interface pointers, it must hold these references in the Global Interface Table (GIT) or as CAObjectHandles with multithreading support enabled. |
Miscellaneous Notes on COM Threading Models
The LabWindows/CVI ActiveX Library initializes the COM library and sets the COM threading model of an EXE server’s main thread based on the server threading model. If a DLL or EXE server creates additional threads that call ActiveX code, then those threads must set their COM threading model by calling CA_InitActiveXThreadStyleForCurrentThread with the required threading model.
If an ActiveX object holds interface pointers to other objects, it should hold the objects as type CAObjHandle. The LabWindows/CVI ActiveX Library uses the type CAObjHandle to hold an external ActiveX object reference. If the CAObjHandle must be used from a thread other than the thread in which it was obtained, then multithreading must be enabled for the CAObjHandle. To enable multithreading for the CAObjHandle, specify the multithreading setting in the creation function that gets the CAObjHandle or call CA_SetSupportForMultithreading after getting the CAObjHandle. If you do not use a CAObjHandle to hold interface pointers, you must use the GIT to store and access interface pointers from multiple threads. The GIT is described on www.msdn.com.
Be careful when creating in-process DLL servers that perform user interface tasks. The user interface components in a DLL server should be completely self-contained in the DLL. Try to avoid any possible conflicting interactions with the client process that is using the DLL server. For example, be careful when the server accesses windows that were created by the client process—if the server and client run on different threads, this can lead to a deadlock. Note that these kinds of deadlocks can happen even when using functions like printf from the DLL server because, if you use the LabWindows/CVI stdio window, the windows written to by the server would have been created by the client process during program start-up. In this situation, NI recommends that you create the program as a console application or use some other printing mechanism.