is COM technology out of date? That's not true either. Technically, it is true that COM usage is declining, but intellectually, the idea of COM's interface-oriented is being carried forward by Java and. Net. So we still need to deal with COM. It depends on the area of your work. Although now Microsoft's platform is slowly toward. Net migration, COM is more or less inevitable when it comes to maintaining legacy unmanaged code, writing programs that deal with Windows system components, and using the CLR to invoke unmanaged code. It's impossible to deal with COM without talking about suites (apartments). Suite is a very useful but also very difficult to understand a concept in COM, you can say that many of the problems in COM and suites, understand the suite, from fully understand COM is a step closer, this article will discuss the basic knowledge of the suite and in. NET in the application.
What is a suite (apartments)
Suite is a set of mechanisms for COM to simplify object support for multithreading, to specify the multithreaded nature of threads and COM objects, and to provide synchronous support for calls between suites with different features. To ensure that objects with different multithreaded features can be invoked correctly with each other without introducing synchronization problems, simplifying programming (which may actually be more complex). For example, if an object is written to forget to consider multithreading, or have no time to consider, or do not need to provide support for multithreaded, this time you can designate the object as STA, let COM automatically manage the call to the object, to ensure that the object can be called correctly, Even multi-threaded calls are serialized (called in turn, not simultaneous calls). Conversely, if an object supports multi-threaded invocation, it can be marked as mta,com and allows for multi-threaded invocation of it.
The following are some things to keep in mind about the suite:
1. The suite is not a real area, but a logical concept
2. The suite shows the multithreaded nature of the code in the suite, which determines the following
A. Does the code itself allow single-threaded calls or multithreaded calls
B. Code creation COM objects get a proxy or a raw pointer (see the following proxy section for proxy)
C. Code calls between the same set of COM objects is through the original pointer, different suites are via proxy
3. A thread must belong to a suite, which indicates the multithreaded nature of the thread itself, that is, whether the thread calls a COM object on a multithreaded or single-threaded call. For example, if a thread is in the STA, the thread is only suitable for direct calls to the same set of COM objects that support single-threaded calls, and other COM objects need to be invoked indirectly via proxy, what the proxy will say later. At the same time, the suite that the thread is in also determines whether the object itself or proxy is obtained when the object is created. Threads can only belong to one suite at a time or not to a single suite, but the threads may belong to different suites at different times. A typical example is when a thread invokes the CoInitialize and then calls CoUninitialize out of the suite, then calls CoInitialize into another suite, and the thread temporarily enters NTA is an example. Here's what we'll talk about.
4. COM objects must also belong to a suite, which in the same way determines the multithreaded nature of COM objects, similar to the above. COM objects are not migrated from one suite to another, and if the suite is released, the fact that the object is released at the same time is particularly important for the STA suite.
5. Cross-suite must be through proxy, which is the basis for COM guarantee suite to work. The following proxy section will talk about why.
Type of suite (apartments)
Common apartments have STA and MTA, and a new suite NTA is introduced in the Win2000. STA is used for single-threaded, MTA is used for multithreading. NTA, however, is called thread-independent (thread-neutral) multithreading. In short, the difference between Sta,mta,nta is shown in the following table:
Cross-suite can be executed on any thread threads can belong to the suite multithreading features. a message loop is required. number of en-suite threads in the process
STA No Yes single thread yes unrestricted 1
MTA No Yes multithreading No 1 unrestricted
NTA Yes no multithreading No 1 unrestricted
The features, differences, and programming considerations for each suite are explained in detail later in this article.
Threads and Suites
The thread enters the suite by calling CoInitialize/CoInitializeEx and then exits the suite via CoUninitialize. Entering the suite may result in the suite being created, and the same couninitialize call will result in the suite being released. The number of calls to CoInitialize and CoUninitialize must match, similar to addref/release.
CoInitialize can only enter the STA suite, and CoInitializeEx can enter the different suites through the incoming parameters, the incoming coinit_apartmenthreaded into the STA, and the incoming Coinit_ multithreaded into the MTA. When the coinitialize/counintiialize is invoked, the thread belongs to the suite, and if the STA is specified, the new STA will always be created, and if the MTA is specified, a new MTA is created if the MTA does not exist. The attentive friend may have noticed that there are 3 kinds of suites mentioned above, so where is NTA running? In fact, a thread does not belong to the NTA, the thread can only temporarily enter the Nta,nta can only exist objects.
Objects and Apartments
COM objects always belong to a suite. COM objects in the registry can specify the type of suite the object expects by the ThreadingModel property, valid values are:
Property Value meaning
Main ( default ) primary STA, which is the first STA created
Apartment Sta
Both STA or MTA can
Free Mta
Neutral NTA
It should be explained that, from the suite point of view, the main STA and other non-main STA is not different, but specifically designated as the main Sta.
The relationship between the thread suite and the object suite
As you can see, the threads also have a suite, and the object also has a suite, so what is the relationship between the two? This is a relatively confusing problem. In fact, in simple terms, the object's suite setting determines which suite the object is in, and the thread's suite determines the thread's suite. OK, see here you may say, this is not equal to not say. Oh, this is really the most essential difference, however, the other two suites also determine the other point, that is, the compatibility of the suite and the object is in the same suite . This is important because it determines whether the pointer to the object returned by the CoCreateInstance is the original pointer or proxy(here is a discussion of the inside of the process, the proxy is always outside the process). For example, if the thread's suite is an STA and the object's suite is also an STA, then the object is created in the STA where the thread is located, whereas if the threads are in the apartment of an STA and the object's suite is an MTA, then the object is created in the unique MTA suite. The thread gets the proxy (proxy) of the object, not the original pointer. The concept of an agent will be mentioned later.
There is a table in MSDN that is slightly modified here, listed below:
Object Suite =main Object Suite =apartment Object Suite =both Object Suite =free Object Suite =neutral
Thread Suite = Main STA main STA current thread suite current thread suite MTA NTA
Thread Suite =sta Current thread suite current thread suite current thread suite MTA NTA
Thread Suite =mta main STA sta current thread suite MTA (current thread's suite) NTA
Thread Suite =nta main STA sta NTA MTA NTA
Across Suites (cross-apartment), proxy/stub and marshalling
Suite calls in this suite do not require a proxy, it is a direct call, and ordinary C + + virtual function calls are no different. COM's powerful place (and it's not too easy to understand) is that it can be implemented by proxy for thread safety. Let's use a practical example to consider this problem, if two MTA threads call object A in an STA at the same time, because it is in the STA, the object is written without taking into account multithreaded issues and therefore needs protection. If a two-MTA thread invokes the method of a at the same time through the pointer pa of a, it is obviously not possible to provide thread-safe protection at this time. The solution for COM is that the object A of the two MTA threads is not object a itself, but a proxy. The so-called proxy, refers to the object is not an actual object, but a proxy, is responsible for forwarding the call to its proxy object A, the agent itself does not perform the actual operation. On the server side, there is a piece of code called a stub, responsible for accepting the request from the proxy and actually executing the request. In other words, the proxy is always on the client and the stub is on the server side.
1. Cocreateinstance/cocreateinstancex
Cocreateinstance/cocreateinstancex is a function that must be called to create a COM object that is created in that suite according to the voting object mentioned in the previous section, if the object is created in the current thread suite. A description of the thread's suite and the object's suite are compatible and does not require COM to be processed externally, thus directly returning the object's original interface pointer. Conversely, the description of COM objects and threads of the suite is incompatible, must return an object of the interface of the proxy to deal with these things.
2. marshalling/unmarshalling
Marshalling/unmarshalling, also known as the column set and the scatter set (literal translation), can be roughly understood as serialization/deserialization, i.e. serialization and drag. The interface pointer between suites must pass through this process, in fact, the above situation is a common marshalling/unmarshalling special case. If suite A is going to transfer the interface pointer to suite B, you cannot pass the pointer over it, but you must go through the following procedure:
A. Suite A marshal the interface pointer to a IStream object (also a COM object), generally through comarshalinterthreadinterfaceinstream, and a more powerful function is comarshalinterface. This marshal is implemented through the IMarshal interface, and COM has the default IMarshal implementation.
B. Suite A passes the IStream interface pointer to the IStream object to suite B
C. Suite B unmarshal The Stream object pointed to by the IStream interface pointer to obtain COM objects based on this suite proxy, generally through cogetinterfaceandreleasestream, or use Unmarshalinterface,
A careful friend may ask, wait, you're not saying that the interface pointer needs proxy, so IStream itself does not need proxy. In fact, the interface pointer of this IStream object is very special, and it can be invoked in different suites.
If you do not follow this principle, what will be the result of passing the pointer directly:
1. If you are lucky, if this pointer is a proxy, then you may report error Rpc_e_wrongthread, indicating that the proxy corresponding to the suite is not in this suite
2. Otherwise, in the call, COM's multithreaded protection will be lost, you will encounter a variety of multithreading-related issues
Therefore, it is important to ensure that the pointer is marshal/unmarshal to obtain a proxy when passing the interface pointer between the different suites.
OK, this time we're going to talk about this, and the next article will focus on the Sta/mta/nta categories. Please pay attention.