Dr. Dobb's is part of the Informa Tech Division of Informa PLC

This site is operated by a business or businesses owned by Informa PLC and all copyright resides with them. Informa PLC's registered office is 5 Howick Place, London SW1P 1WG. Registered in England and Wales. Number 8860726.


Channels ▼
RSS

COM Apartments and .NET Threads


COM Apartments and .NET Threads

The main reason for COM apartments is to control how objects handle synchronization of calls to their methods. A COM object that implements its own synchronization, or does not need synchronization, can run in a multithreaded apartment (MTA), so any thread in the apartment can access the object at any time. An object that needs synchronization (because its methods use thread sensitive data) but does not provide it itself must run in a single-threaded apartment (STA), which guarantees that only a single thread will access the object regardless of the thread that initialized the call. Windows messages are processed via message queues, which are thread based. A COM object that has a GUI must run on the same thread to ensure that windows messages continue to be handled.

Although .NET provides a whole new paradigm for application development (at the moment it is built over Windows), so much of .NET has more than a passing regard to Windows features. Apartment membership is one of the Windows features that affects .NET development. If your .NET code will ever use a COM object via COM interop, then that code must run in a COM apartment. In some cases the use of COM is hidden: If you use drag and drop with a .NET Control, then you will need a COM apartment because drag and drop uses OLE. Furthermore, because a Control is a GUI element, the COM apartment must be an STA.

The good news is that .NET will detect that you are about to use COM and will call ::CoInitializeEx() for you. The bad news is that .NET will not know about the objects you will use (or more specifically, how you want to access those objects), so it won't know what apartment type to use. By default, .NET will always initialize an MTA. To make .NET initialize an STA, you have to explicitly indicate that this is your intention. There are two ways to do this: First, you can mark a method with the [STAThread] attribute; and second, you can get access to the current thread and change the ApartmentState property to ApartmentState::STA. Once a thread has joined an apartment, it will always remain in that apartment, so the attribute—or ApartmentState property—will only be consulted once for each thread.

Every process has a single thread pool that contains threads managed by the run time. The thread pool is used in several places in .NET. Most often, you use a thread pool thread explicitly through the ThreadPool::QueueUserWorkItem() method. However, if you make a call through .NET Remoting, the object will be called on a thread pool thread. This is very similar to how remote objects are handled in DCOM: RPC maintains a pool of threads in a COM server application to accept COM activation requests. Another situation is when you make asynchronous calls in .NET—the call will be on a pool thread.

Now, here’s the interesting part. If you have a .NET method that uses COM, the thread must initialize an apartment. If you want to call the method asynchronously, then the thread will be a pool thread, and you cannot guarantee which thread will be used. Thus, the method that is called asynchronously must be marked with [MTAThread] or explicitly set the ApartmentState to ApartmentState::MTA. If you attempt to set the apartment to STA, then .NET will override you and set the apartment to MTA because the thread is a pool thread and cannot be devoted to accessing a single object. If you want to access an STA object through a method called asynchronously, there is no problem because COM will create the object in an appropriate apartment, and access will be through a proxy. If the method will create many such STA objects that will access each other, proxies impose a performance overhead. To handle this case, your asynchronous method can create a new thread, initialize it to be used in an STA, and then call the COM object on that thread.


Richard Grimes speaks at conferences and writes extensively on .NET, COM, and COM+. He is the author of Developing Applications with Visual Studio .NET (Addison-Wesley, 2002). If you have comments about this topic, Richard can be reached at [email protected].



Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.