Behavior of the COM Threading Models


Before any thread can create or manipulate COM objects, it must perform
some preliminary initialization to establish its relationship with the
COM library. As a result of this process, COM creates an apartment
appropriate for the initialization routine: CoInitialize creates a
single-threaded apartment (STA), whereas CoInitializeEx with the
COINIT_MULTITHREADED flag produces a multi-threaded apartment.
The CoInitialize/CoInitializeEx call does not initialize the COM
library globally, only the calling thread’s use of it, so it’s important
to remember that this initialization should be done on a per-thread
basis. This is typically done early in a thread’s work function


A single-threaded apartment is associated with the thread that created
it, and only that specific thread may execute calls on objects within
the apartment. By contrast, a multi-threaded apartment is not associated
with any particular thread. It may be called concurrently by any number
of threads and objects within it and should subsequently protect their
member data.


Communication between apartments is done via marshaling, a generic
abstraction for passing data across thread or process boundaries.
Because calls to single-threaded apartments can only be executed on the
thread that created them, other threads that wish to use an object
within this apartment marshal the call to the apartment’s thread and let
the apartment thread execute the call. The apartment thread then
marshals the return value back to the calling thread.


Choosing the threading model for an object depends on the object’s
function. An object that does extensive I/O might support free-threading
to provide maximum response to clients by allowing interface calls
during I/O latency. On the other hand, an object that interacts with the
user might support apartment threading to synchronize incoming COM calls
with its window operations.


It is easier to support apartment threading in single-threaded
apartments because COM provides synchronization on a per-call basis.
Supporting free-threading is more difficult because the object must
implement synchronization; however, response to clients may be better
because synchronization can be implemented for smaller sections of

Processes, Threads, and

process is a collection of virtual memory space, code, data, and
system resources. A thread is code that is to be serially executed
within a process. A processor executes threads, not processes, so each
application has at least one process, and a process always has at least
one thread of execution, known as the primary thread. A process can have
multiple threads in addition to the primary thread.

Processes communicate with one another through messages, using
Microsoft’s Remote Procedure Call (RPC) technology to pass information
to one another. There is no difference to the caller between a call
coming from a process on a remote machine and a call coming from another
process on the same machine.

When a thread begins to execute, it continues until it is killed or
until it is interrupted by a thread with higher priority (by a user
action or the kernel’s thread scheduler). Each thread can run separate
sections of code, or multiple threads can execute the same section of
code. Threads executing the same block of code maintain separate stacks.
Each thread in a process shares that process’s global variables and

The thread scheduler determines when and how often to execute a thread,
according to a combination of the process’s priority class attribute and
the thread’s base priority. You set a process’s priority class attribute
by calling the SetPriorityClass.aspx) function
, and you set a thread’s base priority with a call to SetThreadPriority.aspx).

Multithreaded applications must avoid two threading
problems: deadlocks and races. A deadlock occurs when each thread is
waiting for the other to do something. The COM call control helps
prevent deadlocks in calls between objects. A race condition occurs when
one thread finishes before another on which it depends, causing the
former to use an uninitialized value because the latter has not yet
supplied a valid one. COM supplies some functions specifically designed
to help avoid race conditions in out-of-process servers. (See Out-of-Process Server Implementation

The Apartment and the COM Threading Architecture

While COM supports the single-thread-per-process model prevalent before
the introduction of multiple threads of execution, writing code to take
advantage of multiple threads makes it possible to create more efficient
applications than ever before by allowing a thread, while it waits for
some time-consuming operation to complete, to allow another thread to be

Note   Using multiple threads is not a guarantee of better
performance. In fact, because thread factoring is a difficult problem,
using multiple threads often causes performance problems. The key is to
use multiple threads only if you are very sure of what you are doing.

In general, the simplest way to view the COM threading architecture is
to think of all the COM objects in the process as divided into groups
called apartments. A COM object lives in exactly one apartment, in the
sense that its methods can legally be directly called only by a thread
that belongs to that apartment. Any other thread that wants to call the
object must go through a proxy.

There are two types of apartments: single-threaded
and multithreaded

  • Single-threaded apartments consist of exactly one thread, so all COM
    objects that live in a single-threaded apartment can receive method
    calls only from the one thread that belongs to that apartment. All
    method calls to a COM object in a single-threaded apartment are
    synchronized with the windows message queue for the single-threaded
    apartment’s thread. A process with a single thread of execution is
    simply a special case of this model.
  • Multithreaded apartments consist of one or more threads, so all COM
    objects that live in an multithreaded apartment can receive method
    calls directly from any of the threads that belong to the
    multithreaded apartment. Threads in a multithreaded apartment use a
    model called free-threading. Calls to COM objects in a
    multithreaded apartment are synchronized by the objects themselves.

Note   For a description of communication between single-threaded
apartments and multithreaded apartments within the same process,
see Single-Threaded and Multithreaded

A process can have zero or more single-threaded apartments and zero or
one multithreaded apartment.

In a process, the main apartment is the first to be initialized. In a
single-threaded process, this is the only apartment. Call parameters are
marshaled between apartments, and COM handles the synchronization
through messaging. If you designate multiple threads in a process to be
free-threaded, all free threads reside in a single apartment, parameters
are passed directly to any thread in the apartment, and you must handle
all synchronization. In a process with both free-threading and apartment
threading, all free threads reside in a single apartment and all other
apartments are single-threaded apartments. A process that does COM work
is a collection of apartments with, at most, one multithreaded apartment
but any number of single-threaded apartments.

The threading models in COM provide the mechanism for clients and
servers that use different threading architectures to work together.
Calls among objects with different threading models in different
processes are naturally supported. From the perspective of the calling
object, all calls to objects outside a process behave identically, no
matter how the object being called is threaded. Likewise, from the
perspective of the object being called, arriving calls behave
identically, regardless of the threading model of the caller.

Interaction between a client and an out-of-process object is
straightforward, even when they use different threading models because
the client and object are in different processes. COM, interposed
between the client and the server, can provide the code for the
threading models to interoperate, using standard marshaling and RPC. For
example, if a single-threaded object is called simultaneously by
multiple free-threaded clients, the calls will be synchronized by COM by
placing corresponding window messages in the server’s message queue. The
object’s apartment will receive one call each time it retrieves and
dispatches messages. However, some care must be taken to ensure that
in-process servers interact properly with their clients. (See In-Process Server Threading

The most important issue in programming with a multithreaded model is to
make your code thread-safe so that messages intended for a particular
thread go only to that thread and access to threads is protected.

In-Process Server Threading

An in-process server does not call CoInitialize.aspx), CoInitializeEx.aspx),
or OleInitialize.aspx) to
mark its threading model. For thread-aware DLL-based or in-process
objects, you need to set the threading model in the registry. The
default model when you do not specify a threading model is
single-thread-per-process. To specify a model, you add
theThreadingModel value to the InprocServer32.aspx) key
in the registry.

DLLs that support instantiation of a class object must implement and
export the functions DllGetClassObject.aspx)and DllCanUnloadNow.aspx).
When a client wants an instance of the class the DLL supports, a call
toCoGetClassObject.aspx) (either
directly or through a call to CoCreateInstance.aspx))
calls DllGetClassObject to get a pointer to its class object when
the object is implemented in a DLL. DllGetClassObject should
therefore be able to give away multiple class objects or a single
thread-safe object (essentially just usingInterlockedIncrement.aspx)/InterlockedDecrement.aspx) on
their internal reference counts).

As its name implies, DllCanUnloadNow.aspx) is
called to determine whether the DLL that implements it is in use,
enabling the caller to safely unload it if it is not. Calls to CoFreeUnusedLibraries.aspx) from
any thread always route through the main apartment’s thread to
call DllCanUnloadNow.

Like other servers, in-process servers can be single-threaded,
apartment-threaded, or free-threaded. These servers can be used by any
OLE client, regardless of the threading model used by that client.

All combinations of threading model interoperability are allowed between
clients and in-process objects. Interaction between a client and an
in-process object that use different threading models is exactly like
the interaction between clients and out-of-process servers. For an
in-process server, when the threading model of the client and in-process
server differ, COM must interpose itself between the client and the

When an in-process object that supports the single-threaded model is
called simultaneously by multiple threads of a client, COM cannot allow
the client threads to directly access the object’s interface—the object
was not designed for such access. Instead, COM must ensure that calls
are synchronized and are made only by the client thread that created the
object. Therefore, COM creates the object in the client’s main apartment
and requires all the other client apartments to access the object by
using proxies.

When a free-threaded apartment (multithreaded apartment model) in a
client creates an apartment-threaded in-process server, COM spins up a
single-threaded apartment model “host” thread in the client. This host
thread will create the object, and the interface pointer will be
marshaled back to the client’s free-threaded apartment. Similarly, when
a single-threaded apartment in an apartment-model client creates a
free-threaded in-process server, COM spins up a free-threaded host
thread (multithreaded apartment on which the object will be created and
then marshaled back to the client single-threaded apartment).

Note   In general, if you design a custom interface on an in-process
server, you should also provide the marshaling code for it so that COM
can marshal the interface between client apartments.

COM helps protect access to objects provided by a single-threaded DLL by
requiring access from the same client apartment in which they were
created. In addition, all of the DLL entry points (like DllGetClassObject.aspx) andDllCanUnloadNow.aspx))
and global data should always be accessed by the same apartment. COM
creates such objects in the main apartment of the client, giving the
main apartment direct access to the object’s pointers. Calls from the
other apartments use interthread marshaling to go from the proxy to the
stub in the main apartment and then to the object. This allows COM to
synchronize calls to the object. Interthread calls are slow, so it is
recommended that these servers be rewritten to support multiple

Like a single-threaded in-process server, an object provided by an
apartment model DLL must be accessed by the same client apartment from
which it was created. However, objects provided by this server can be
created in multiple apartments of the client, so the server must
implement its entry points (like DllGetClassObject.aspx) andDllCanUnloadNow.aspx))
for multithreaded use. For example, if two apartments of a client try to
create two instances of the in-process object
simultaneously, DllGetClassObject can be called simultaneously by
both apartments.DllCanUnloadNow must be written so that the DLL does
not unload while code is still executing in the DLL.

If the DLL provides only one instance of the class factory to create all
the objects, the class factory implementation must also be designed for
multithreaded use, because it will be accessed by multiple client
apartments. If the DLL creates a new instance of the class factory each
time DllGetClassObject.aspx) is
called, the class factory need not be thread-safe.

Objects created by the class factory need not be thread-safe. Once
created by a thread, the object is always accessed through that thread
and all calls to the object are synchronized by COM. The apartment model
apartment of a client that creates this object will get a direct pointer
to the object. Client apartments that are different from the apartment
in which the object was created must access the object through proxies.
These proxies are created when the client marshals the interface between
its apartments.

When an in-process DLL ThreadingModel value is set to “Both”, an
object provided by this DLL can be created and used directly (without a
proxy) in single-threaded or multithreaded client apartments. However,
it can be used directly only within the apartment in which it was
created. To give the object to any other apartment, the object must be
marshaled. The DLL object must implement its own synchronization and can
be accessed by multiple client apartments at the same time.

To speed performance for free-threaded access to in-process DLL objects,
COM provides theCoCreateFreeThreadedMarshaler.aspx) function.
This function creates a free-threaded marshaling object that can be
aggregated with an in-process server object. When a client apartment in
the same process needs access to an object in another apartment,
aggregating the free-threaded marshaler provides the client with a
direct pointer to the server object, rather than to a proxy, when the
client marshals the object’s interface to a different apartment. The
client does not need to do any synchronization. This works only within
the same process—standard marshaling is used for a reference to the
object that is sent to another process.

An object provided by an in-process DLL that supports only free
threading is a free-threaded object. It implements its own
synchronization and can be accessed by multiple client threads at the
same time. This server does not marshal interfaces between threads, so
this server can be created and used directly (without a proxy) only by
multithreaded apartments in a client. Single-threaded apartments that
create it will access it through a proxy.



Using single-threaded apartments (the apartment model process) offers a
message-based paradigm for dealing with multiple objects running
concurrently. It enables you to write more efficient code by allowing a
thread, while it waits for some time-consuming operation to complete, to
allow another thread to be executed.

Each thread in a process that is initialized as an apartment model
process, and that retrieves and dispatches window messages, is a
single-threaded apartment thread. Each thread lives within its own
apartment. Within an apartment, interface pointers can be passed without
marshaling, and therefore, all objects in one single-threaded apartment
thread communicate directly.

A logical grouping of related objects that all execute on the same
thread, and therefore must have synchronous execution, could live on the
same single-threaded apartment thread. However, an apartment model
object cannot reside on more than one thread. Calls to objects in other
processes must be made within the context of the owning process, so
distributed COM switches threads for you automatically when you call on
a proxy.

The interprocess and interthread models are similar. When it is
necessary to pass an interface pointer to an object in another apartment
(on another thread) within the same process, you use the same marshaling
model that objects in different processes use to pass pointers across
process boundaries. By getting a pointer to the standard marshaling
object, you can marshal interface pointers across thread boundaries
(between apartments) in the same way you do between processes.
(Interface pointers must be marshaled when passed between apartments.)

Rules for single-threaded apartments are simple, but it is important to
follow them carefully:

  • Every object should live on only one thread (within a
    single-threaded apartment).
  • Initialize the COM library for each thread.
  • Marshal all pointers to objects when passing them between
  • Each single-threaded apartment must have a message loop to handle
    calls from other processes and apartments within the same process.
    Single-threaded apartments without objects (client only) also need a
    message loop to dispatch the broadcast messages that some
    applications use.
  • DLL-based or in-process objects do not call the COM initialization
    functions; instead, they register their threading model with
    the ThreadingModel named-value under the InprocServer32.aspx) key
    in the registry. Apartment-aware objects must also write DLL entry
    points carefully. There are special considerations that apply to
    threading in-process servers. For more information, see In-Process Server Threading

While multiple objects can live on a single thread, no apartment model
object can live on more than one thread.

Each thread of a client process or out-of-process server must
call CoInitialize.aspx),
or call CoInitializeEx.aspx) and
specify COINIT_APARTMENTTHREADED for the dwCoInit parameter. The main
apartment is the thread that calls CoInitializeEx first. For
information on in-process servers, see In-Process Server Threading

All calls to an object must be made on its thread (within its
apartment). It is forbidden to call an object directly from another
thread; using objects in this free-threaded manner could cause problems
for applications. The implication of this rule is that all pointers to
objects must be marshaled when passed between apartments. COM provides
the following two functions for this purpose:

These functions wrap calls to CoMarshalInterface.aspx) and CoUnmarshalInterface.aspx) functions,
which require the use of the MSHCTX_INPROC flag.

In general, the marshaling is accomplished automatically by COM. For
example, when passing an interface pointer as a parameter in a method
call on a proxy to an object in another apartment, or when
COM does the marshaling automatically. However, in some special cases,
where the application writer is passing interface pointers between
apartments without using the normal COM mechanisms, the writer must
handle the marshaling manually.

If one apartment (Apartment 1) in a process has an interface pointer and
another apartment (Apartment 2) requires its use, Apartment 1 must
call CoMarshalInterThreadInterfaceInStream.aspx) to
marshal the interface. The stream that is created by this function is
thread-safe and must be stored in a variable that is accessible by
Apartment 2. Apartment 2 must pass this stream to CoGetInterfaceAndReleaseStream.aspx) to
unmarshal the interface and will get back a pointer to a proxy through
which it can access the interface. The main apartment must remain alive
until the client has completed all COM work (because some in-process
objects are loaded in the main apartment, as described in In-Process Server Threading
After one object has been passed between threads in this manner, it is
very easy to pass interface pointers as parameters. That way,
distributed COM does the marshaling and thread switching for the

To handle calls from other processes and apartments within the same
process, each single-threaded apartment must have a message loop. This
means that the thread’s work function must have a
GetMessage/DispatchMessage loop. If other synchronization primitives are
being used to communicate between threads, the MsgWaitForMultipleObjects.aspx) function
can be used to wait both for messages and for thread synchronization
events. The documentation for this function has an example of this sort
of combination loop.

COM creates a hidden window using the Windows class
“OleMainThreadWndClass” in each single-threaded apartment. A call to an
object is received as a window message to this hidden window. When the
object’s apartment retrieves and dispatches the message, the hidden
window will receive it. The window procedure will then call the
corresponding interface method of the object.

When multiple clients call an object, the calls are queued in the
message queue and the object will receive a call each time its apartment
retrieves and dispatches messages. Because the calls are synchronized by
COM and the calls are always delivered by the thread that belongs to the
object’s apartment, the object’s interface implementations need not
provide synchronization. Single-threaded apartments can
implement IMessageFilter.aspx)to
permit them to cancel calls or receive window messages when necessary.

The object can be reentered if one of its interface method
implementations retrieves and dispatches messages or makes an ORPC call
to another thread, thereby causing another call to be delivered to the
object (by the same apartment). OLE does not prevent reentrancy on the
same thread, but it can help provide thread safety. This is identical to
the way in which a window procedure can be reentered if it retrieves and
dispatches messages while processing a message. However, calling an
out-of-process single-threaded apartment server that calls another
single-threaded apartment server will allow the first server to be

Accessing Interfaces Across

COM provides a way for any apartment in a process to get access to an
interface implemented on an object in any other apartment in the
process. This is done through the IGlobalInterfaceTable.aspx) interface.
This interface has three methods, which allow you to do the following:

  • Register an interface as a global (processwide) interface.
  • Get a pointer to that interface from any other apartment through a
  • Revoke the global registration of an interface.

The IGlobalInterfaceTable.aspx) interface
is an efficient way for a process to store an interface pointer in a
memory location that can be accessed from multiple apartments within the
process, such as process-wide variables andagile objects
(free-threaded, marshaled objects) containing interface pointers to
other objects.

An agile object is unaware of the underlying COM infrastructure in which
it runs; in other words, what apartment, context, and thread it is
executing on. The object may be holding on to interfaces that are
specific to an apartment or context. For this reason, calling these
interfaces from wherever the agile component is executing might not
always work properly. The global interface table avoids this problem by
guaranteeing that a valid proxy (or direct pointer) to the object is
used, based on where the agile object is executing.

Note   The global interface table is not portable across process or
machine boundaries, so it cannot be used in place of the normal
parameter-passing mechanism.

When to Use the Global
Interface Table

If you are unmarshaling an interface pointer multiple times between
apartments in a process, you might use theIGlobalInterfaceTable.aspx) interface.
With other techniques, you would have to remarshal each time.

Note   If the interface pointer is unmarshaled only once, you may
want to use theCoMarshalInterThreadInterfaceInStream.aspx) function.
It can also be used to pass an interface pointer from one thread to
another thread in the same process.

The IGlobalInterfaceTable.aspx) interface
also makes another previously difficult problem simpler for the
programmer. This problem occurs when the following conditions apply:

  • An in-process agile object aggregates the free-threaded marshaler.
  • This same agile object also holds (as member variables) interface
    pointers to other objects that are not agile and do not aggregate
    the free-threaded marshaler.

In this situation, if the outer object gets marshaled to another
apartment and the application calls on it, and the object tries to call
on any of its member variable interface pointers that are not
free-threaded or are proxies to objects in other apartments, it might
get incorrect results or the error RPC_E_WRONG_THREAD. This error
occurs because the inner interface is designed to be callable only from
the apartment in which it was first stored in the member variable.

To solve this problem, the outer object aggregating the free-threaded
marshaler should callIGlobalInterfaceTable::RegisterInterfaceInGlobal.aspx) on
the inner interface and store the resulting cookie in its member
variable, instead of storing the actual interface pointer. When the
outer object wants to call on an inner object’s interface pointer, it
should call IGlobalInterfaceTable::GetInterfaceFromGlobal.aspx),
use the returned interface pointer, and then release it. When the outer
object goes away, it should callIGlobalInterfaceTable::RevokeInterfaceFromGlobal.aspx) to
remove the interface from the global interface table

Use the following call to create the global interface table object and
get a pointer to IGlobalInterfaceTable.aspx):

hr = CoCreateInstance(CLSID_StdGlobalInterfaceTable,
                 (void **)&gpGIT);
if (hr != S_OK) {
  exit(0); // Handle errors here.

Note   When creating the global interface table object using the
preceding call, it is necessary to link to the library uuid.lib. This
will resolve the external symbols CLSID_StdGlobalInterfaceTable and

There is a single instance of the global interface table per process, so
all calls to this function in a process return the same instance.

After the call to the CoCreateInstance.aspx) function,
register the interface from the apartment in which it resides with a
call to the RegisterInterfaceInGlobal.aspx) method.
This method supplies a cookie that identifies the interface and its
location. An apartment seeking a pointer to this interface then calls
the GetInterfaceFromGlobal.aspx)method
with this cookie, and the implementation then supplies an interface
pointer to the calling apartment. To revoke the interface’s global
registration, any apartment can call the RevokeInterfaceFromGlobal.aspx) method.

A simple example of using IGlobalInterfaceTable.aspx) would
be when you want to pass an interface pointer on an object in a
single-threaded apartment (STA) to a worker thread in another apartment.
Rather than having to marshal it into a stream and pass the stream to
the worker thread as a thread parameter,IGlobalInterfaceTable allows
you simply to pass a cookie.

When you register the interface in the global interface table, you get a
cookie that you can use instead of passing the actual pointer (whenever
you need to pass the pointer), either to a nonmethod parameter that is
going to another apartment (as a parameter to ThreadProc.aspx) through CreateThread.aspx))
or to in-process memory accessible outside your apartment.

Care is required because using global interfaces places the extra burden
on the programmer of managing problems such as race conditions and
mutual exclusion, which are associated with accessing global state from
multiple threads simultaneously.

COM provides a standard implementation of the IGlobalInterfaceTable.aspx) interface.
It is highly recommended that you use this standard implementation
because it provides complete thread-safe functionality.

Multithreaded Apartments

In a multithreaded apartment model, all the threads in the process that
have been initialized as free-threaded reside in a single apartment.
Therefore, there is no need to marshal between threads. The threads need
not retrieve and dispatch messages because COM does not use window
messages in this model.

Calls to methods of objects in the multithreaded apartment can be run on
any thread in the apartment. There is no serialization of calls; many
calls may occur to the same method or to the same object simultaneously.
Objects created in the multithreaded apartment must be able to handle
calls on their methods from other threads at any time.

Because calls to objects are not serialized in any way, multithreaded
object concurrency offers the highest performance and takes the best
advantage of multiprocessor hardware for cross-thread, cross-process,
and cross-machine calling. This means, however, that the code for
objects must provide synchronization in their interface implementations,
typically through the use of synchronization primitives such as event
objects, critical sections, mutexes, or semaphores, which are described
later in this section. In addition, because the object doesn’t control
the lifetime of the threads that are accessing it, no thread-specific
state may be stored in the object (in thread local storage).

Following are some important considerations regarding synchronization
for multithreaded apartments:

  • COM provides call synchronization for single-threaded apartments
  • Multithreaded apartments do not receive calls while making calls (on
    the same thread).
  • Multithreaded apartments cannot make input-synchronized calls.
  • Asynchronous calls are converted to synchronous calls in
    multithreaded apartments.
  • The message filter is not called for any thread in a multithreaded

To initialize a thread as free-threaded, call CoInitializeEx.aspx),
specifying COINIT_MULTITHREADED. For information on in-process server
threading, see In-Process Server

Multiple clients can simultaneously call, from different threads, an
object that supports free-threading. In free-threaded out-of-process
servers, COM, through the RPC subsystem, creates a pool of threads in
the server process and a client call (or multiple client calls) can be
delivered by any of these threads at any time. An out-of-process server
must also implement synchronization in its class factory. Free-threaded,
in-process objects can receive direct calls from multiple threads of the

The client can do COM work in multiple threads. All threads belong to
the same multithreaded apartment. Interface pointers are passed directly
from thread to thread within a multithreaded apartment, so interface
pointers are not marshaled between its threads. Message filters
(implementations of IMessageFilter.aspx))
are not used in multithreaded apartments. The client thread will suspend
when it makes a COM call to out-of-apartment objects and will resume
when the call returns. Calls between processes are still handled by RPC.

Threads initialized with the free-threaded model must implement their
own synchronization. As mentioned earlier in this section, Windows
enables this implementation through the following synchronization

  • Event objects provide a way of signaling one or more threads that an
    event has occurred. Any thread within a process can create an event
    object. A handle to the event is returned by the event-creating
    function, CreateEvent.aspx).
    Once an event object has been created, threads with a handle to the
    object can wait on it before continuing execution.
  • Critical sections are used for a section of code that requires
    exclusive access to some set of shared data before it can be
    executed and that is used only by the threads within a single
    process. A critical section is like a turnstile through which only
    one thread at a time may pass, working as follows:

    • To ensure that no more than one thread at a time accesses shared
      data, a process’s primary thread allocates a global
      CRITICAL_SECTION data structure and initializes its members. A
      thread entering a critical section calls the EnterCriticalSection.aspx) function
      and modifies the data structure’s members.
    • A thread attempting to enter a critical section calls EnterCriticalSection.aspx) which
      checks to see whether the CRITICAL_SECTION data structure has
      been modified. If so, another thread is currently in the
      critical section and the subsequent thread is put to sleep. A
      thread leaving a critical section calls LeaveCriticalSection.aspx),
      which resets the data structure. When a thread leaves a critical
      section, the system wakes one of the sleeping threads, which
      then enters the critical section.
  • Mutexes performs the same function as a critical section, except
    that the mutex is accessible to threads running in different
    processes. Owning a mutex object is like having the floor in a
    debate. A process creates a mutex object by calling the CreateMutex.aspx) function,
    which returns a handle. The first thread requesting a mutex object
    obtains ownership of it. When the thread has finished with the
    mutex, ownership passes to other threads on a first-come,
    first-served basis.
  • Semaphores are used to maintain a reference count on some available
    resource. A thread creates a semaphore for a resource by calling
    the CreateSemaphore.aspx) function
    and passing a pointer to the resource, an initial resource count,
    and the maximum resource count. This function returns a handle. A
    thread requesting a resource passes its semaphore handle in a call
    to the WaitForSingleObject.aspx)function.
    The semaphore object polls the resource to determine whether it is
    available. If so, the semaphore decrements the resource count and
    wakes the waiting thread. If the count is zero, the thread remains
    asleep until another thread releases a resource, causing the
    semaphore to increment the count to one.











 图片 1图片 2图片 3图片 4

  COM Runtime将创立STA

Runtime将为那几个COM对象创立三个新的线程并在那一个新线程中树立STA COM对象,

Runtime将为那几个COM对象建设构造贰个新的线程并在那些新线程中成立MTA COM对象,

  假诺那一个COM对象未有被确立过,COM Runtime将创立MTA COM对象.COM

  如若这几个COM对象未有被初阶化过,COM Runtime将确立STA

  固然那一个COM对象未有被伊始化过,COM Runtime将确立MTA

  1. 关于marshal
      在COM中marshal分为二种: 进度内的marshal, 同一Computer中经过间的marshal,
    以及差别计算机间的marshal. 进程内和经过间的marshal是因此Local
    RPC达成的,Computer间的marshal通过DCE RPC来落成.
    举个例证来讲, 三个处在MTA中的Client线程,想要调用三个地处STA中的对象时,
    COM Runtime会走进去, 对这些调用进行marshal.为何要marshal?
    必要求收获对该对象的调用, 然后打开排队. marshal正是起那个效率.
    在成就调用后由stub将结果传到Proxy. 对于目的的Interface,
           对于COM+的Thread-Neutral Apartment比较独特,
    COM+提供了一种类新的效应, 如Object Pooling, Object Construct String等.
    依旧形象写,比方: 比方小编有四个COM Server, 它监视三个工控装置的时域信号,
    客商端和自己的COM Server通过IConnectionPoint实现事件触发机制.为了加强质量,
    并将之放到一个Interface指针表里, 主线程运转在STA中.
    为什么, 顾客端通过IConnectionPoint传给我的COM
    Server主线程的Interface指针是机动举办了marshal, 可是, 由于自己的COM
    对这么些线程来讲, 那一个Interface指针是从未有过通过marshal的,
    在调用是就会师世RPC_E_WRONG_THREAD错误. 要消除那个主题材料,有多个点子, 
    1) 让笔者的主线程也运维在MTA中.这种方法轻便.
    2) 手工marshal. 
    更加好的化解方法是利用GIT(global interface table),



7。 若STA创设STA型组件,是一贯创建,直接调用。