Hi,

I have the following problem:
I am getting two independent COM components (say A and B) assigned a single
STA. One of the components (say A) calls a method on a third component C (in
a different STA) that may in turn possibly go out-of-proc from C. Now as soon
as this call goes out-of-proc, a call on component B, which was waiting
outside the apartment all this time (as calls to STA are serialized by COM),
suddenly enters the STA and starts processing. Now, when the out-of-proc call
returns to C and then eventually back to A, it has nowhere to return, as the
thread is already in use by B!

I thought if A and B always belong to different STAs of their own, this
problem will not occur. In that regard, is there any way which can ensure
that a COM component with threadingmodel=Apartment (STA), after it is
CoCreated, will always lie in a different new STA, and not join any other
already existing STA?

Also, do you see any other possible solutions to this problem?

Thanks in advance,

Regards,
Sandeep

Re: Assigning apartment to a COM component by Alex

Alex
Wed Jul 27 07:30:12 CDT 2005

Sandeep wrote:
> I have the following problem:
> I am getting two independent COM components (say A and B)
> assigned a single STA. One of the components (say A)
> calls a method on a third component C (in a different
> STA) that may in turn possibly go out-of-proc from C. Now
> as soon as this call goes out-of-proc, a call on
> component B, which was waiting outside the apartment all
> this time (as calls to STA are serialized by COM),
> suddenly enters the STA and starts processing. Now, when
> the out-of-proc call returns to C and then eventually
> back to A, it has nowhere to return, as the thread is
> already in use by B!

What do you mean by "nowhere to return"? The call made from
A doesn't disappear into void.

What actually happens is that STA appartment is reentered
while A is waiting in a call. See here last paragraph for
explanation:

"Single-Threaded Apartments"
http://msdn.microsoft.com/library/en-us/com/html/2f345ae2-8314-4067-a6d6-5a0275941ed4.asp

It's perfectly legal from COM point of view to reenter the
same STA. Think about it as if it was message procedure
(which actually is) that shows modal dialog box. While
dialog box is open procedure doesn't return. However, it
continues to handle other messages in the same thread. So,
while A component waits on out-of-proc call messages are
dispatched and components (including A) can receive
additional calls.

> I thought if A and B always belong to different STAs of
> their own, this problem will not occur.

I don't quite get it. You said first that A and B exist in
the same STA. Also, if A and B exist in different
appartments, then why it should prevent calls to B object
while A is waiting?

> In that regard,
> is there any way which can ensure that a COM component
> with threadingmodel=Apartment (STA), after it is
> CoCreated, will always lie in a different new STA, and
> not join any other already existing STA?

To ensure that you need to create each object in separate
thread. Then each object will have its own STA.

> Also, do you see any other possible solutions to this
> problem?

Probably you should slightly redesign A and B taking the
possibility of reentrant call into account.



Re: Assigning apartment to a COM component by Sandeep

Sandeep
Wed Jul 27 08:01:05 CDT 2005

Hi Alex,

Thanks for your reply. Yes, you are right, the STA has been reentered due to
a call on B, as A has made a call to another STA which then has made an
out-of-proc call. So A cannot proceed until B finishes with its processing
(or makes an out-of-proc call) so that the thread in the STA is available
again.

> > I thought if A and B always belong to different STAs of
> > their own, this problem will not occur.
>
> I don't quite get it. You said first that A and B exist in
> the same STA. Also, if A and B exist in different
> appartments, then why it should prevent calls to B object
> while A is waiting?
>

Right, I only meant that if A and B live in different apartments, calls made
on either of them will not affect the other. The problem is because A and B
are in the same apartment and the apartment is reentered for a call on B
while call on A is waiting for an out-of-proc call to return. So making sure
(somehow) that A and B always exist in different apartments will get rid of
the issue of calls on B affecting A.

> To ensure that you need to create each object in separate
> thread. Then each object will have its own STA.

Yes, that's certainly a solution. Actually this has triggered another
question in my mind: how does COM decide on which apartment does a newly
created STA object go into. Is it always the case, that the object belongs to
the STA of the thread that created it?

Also, another important question in the same connection: if a client
residing in an MTA creates STA objects, how is it decided which apartments
these objects go into? Do they join any of the existing STAs or is a new STA
is created for any of them? Is there a concrete way of telling this?

Thanks again,

Regards,
Sandeep



"Alex Blekhman" wrote:

> Sandeep wrote:
> > I have the following problem:
> > I am getting two independent COM components (say A and B)
> > assigned a single STA. One of the components (say A)
> > calls a method on a third component C (in a different
> > STA) that may in turn possibly go out-of-proc from C. Now
> > as soon as this call goes out-of-proc, a call on
> > component B, which was waiting outside the apartment all
> > this time (as calls to STA are serialized by COM),
> > suddenly enters the STA and starts processing. Now, when
> > the out-of-proc call returns to C and then eventually
> > back to A, it has nowhere to return, as the thread is
> > already in use by B!
>
> What do you mean by "nowhere to return"? The call made from
> A doesn't disappear into void.
>
> What actually happens is that STA appartment is reentered
> while A is waiting in a call. See here last paragraph for
> explanation:
>
> "Single-Threaded Apartments"
> http://msdn.microsoft.com/library/en-us/com/html/2f345ae2-8314-4067-a6d6-5a0275941ed4.asp
>
> It's perfectly legal from COM point of view to reenter the
> same STA. Think about it as if it was message procedure
> (which actually is) that shows modal dialog box. While
> dialog box is open procedure doesn't return. However, it
> continues to handle other messages in the same thread. So,
> while A component waits on out-of-proc call messages are
> dispatched and components (including A) can receive
> additional calls.
>
> > I thought if A and B always belong to different STAs of
> > their own, this problem will not occur.
>
> I don't quite get it. You said first that A and B exist in
> the same STA. Also, if A and B exist in different
> appartments, then why it should prevent calls to B object
> while A is waiting?
>
> > In that regard,
> > is there any way which can ensure that a COM component
> > with threadingmodel=Apartment (STA), after it is
> > CoCreated, will always lie in a different new STA, and
> > not join any other already existing STA?
>
> To ensure that you need to create each object in separate
> thread. Then each object will have its own STA.
>
> > Also, do you see any other possible solutions to this
> > problem?
>
> Probably you should slightly redesign A and B taking the
> possibility of reentrant call into account.
>
>
>

Re: Assigning apartment to a COM component by Alex

Alex
Wed Jul 27 08:58:03 CDT 2005

Sandeep wrote:
> [...] how does COM
> decide on which apartment does a newly created STA object
> go into. Is it always the case, that the object belongs
> to the STA of the thread that created it?

Actually, it's you who decides in which appartment to create
an object. At some point (usually at a beginning) running
thread "enters" COM apartment: it calls
CoInitialize[Ex]/OleInitialize to specify which kind of
apartment it wants to enter. Then all objects created in
this thread will belong to current appartment (provided they
are compatible with it). Newly created object can't go to
any other apartment because it's already created inside
certain appartment. Object can't change it. Also, you can't
create an object outside an appartment.

> Also, another important question in the same connection:
> if a client residing in an MTA creates STA objects, how
> is it decided which apartments these objects go into? Do
> they join any of the existing STAs or is a new STA is
> created for any of them? Is there a concrete way of
> telling this?

MSDN isn't clear about that. All it says that COM system
will create "host" apartment with appropriate threading
model to create in-proc server, then its interface will be
marshalled back to client's apartment:

Here's mentioned such situation:

"In-Process Server Threading Issues"
http://msdn.microsoft.com/library/en-us/com/html/7bd6f62f-8c91-44bd-9a7f-d47988180eed.asp

---
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.
---

It seems that new thread (i.e. new STA) is created for each
object. You can easily check that by creating sevearl STA
objects from MTA and call some method that will print to
debug output its thread ID.



Re: Assigning apartment to a COM component by Sandeep

Sandeep
Wed Jul 27 09:48:09 CDT 2005

Hi Alex,

Thanks, that was a nice explanation. It certainly made quite a lot of things
clear.

I already tried out watching the thread ids of different STA components
created in an MTA client. To my surprise, I observed that the component
apartment allocation was quite random: for some components a new STA (new
thead id) was getting created, which some others got allocated in the same
apartment (their thread ids were same). Also, their apartment allocation was
different when the MTA client was created from different test applications.

So it seems that to make dead sure that a component gets its own exclusive
STA, it needs to get created in a separate STA thread.

Well, a slight deviation to the original question, but this came to my mind
while thinking over this issue:
Let's assume I have a COM component A, with threadingmodel=Apartment, so
that it always lies in an STA. Its client, though, can have any apartment
model. If A makes a call on a different component say B, which makes an
out-of-proc call. Now if another call on A arrives, it will go in (rerenter)
the component A. So what I have is TWO calls on A have gone in
simultaneously! So, the component A can no more safely assume that it is safe
and all calls on it are strictly serialized. So it will have to make itself
thread-safe.

Is the above thought really true? If it is, then it destroys the very basics
of STA components not having to worry about thread-safety.

Regards,
Sandeep


"Alex Blekhman" wrote:

> Sandeep wrote:
> > [...] how does COM
> > decide on which apartment does a newly created STA object
> > go into. Is it always the case, that the object belongs
> > to the STA of the thread that created it?
>
> Actually, it's you who decides in which appartment to create
> an object. At some point (usually at a beginning) running
> thread "enters" COM apartment: it calls
> CoInitialize[Ex]/OleInitialize to specify which kind of
> apartment it wants to enter. Then all objects created in
> this thread will belong to current appartment (provided they
> are compatible with it). Newly created object can't go to
> any other apartment because it's already created inside
> certain appartment. Object can't change it. Also, you can't
> create an object outside an appartment.
>
> > Also, another important question in the same connection:
> > if a client residing in an MTA creates STA objects, how
> > is it decided which apartments these objects go into? Do
> > they join any of the existing STAs or is a new STA is
> > created for any of them? Is there a concrete way of
> > telling this?
>
> MSDN isn't clear about that. All it says that COM system
> will create "host" apartment with appropriate threading
> model to create in-proc server, then its interface will be
> marshalled back to client's apartment:
>
> Here's mentioned such situation:
>
> "In-Process Server Threading Issues"
> http://msdn.microsoft.com/library/en-us/com/html/7bd6f62f-8c91-44bd-9a7f-d47988180eed.asp
>
> ---
> 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.
> ---
>
> It seems that new thread (i.e. new STA) is created for each
> object. You can easily check that by creating sevearl STA
> objects from MTA and call some method that will print to
> debug output its thread ID.
>
>
>

Re: Assigning apartment to a COM component by Alex

Alex
Wed Jul 27 10:52:49 CDT 2005

Sandeep wrote:
> So it seems that to make dead sure that a component gets
> its own exclusive STA, it needs to get created in a
> separate STA thread.

Yes, it appears so.

> Let's assume I have a COM component A, with
> threadingmodel=Apartment, so that it always lies in an
> STA. Its client, though, can have any apartment model. If
> A makes a call on a different component say B, which
> makes an out-of-proc call. Now if another call on A
> arrives, it will go in (rerenter) the component A. So
> what I have is TWO calls on A have gone in
> simultaneously! So, the component A can no more safely
> assume that it is safe and all calls on it are strictly
> serialized. So it will have to make itself thread-safe.
>
> Is the above thought really true? If it is, then it
> destroys the very basics of STA components not having to
> worry about thread-safety.

STA component is still thread safe in the sense that its
methods cannot execute _simultaneously_. However,
thread-safety doesn't imply protection from reentering.
Whether to ensure call serialization is up to you. After
all, until you avoid code that makes ORPC calls you can
assume that execution flow is serialized. Alternatively, you
can quard youself quite simply:

HRESULT A::foo()
{
if(m_bCallPending)
return E_PENDING;

m_bCallPending = true; // member of A

HRESULT hr = b.bar(); // call to out-of-proc server

m_bCallPending = false;

return hr;
}



Re: Assigning apartment to a COM component by Sandeep

Sandeep
Thu Jul 28 03:23:04 CDT 2005

Hi Alex,

Yes, thanks for the clarification. You are absolutely right.

Regards,
Sandeep


"Alex Blekhman" wrote:

> Sandeep wrote:
> > So it seems that to make dead sure that a component gets
> > its own exclusive STA, it needs to get created in a
> > separate STA thread.
>
> Yes, it appears so.
>
> > Let's assume I have a COM component A, with
> > threadingmodel=Apartment, so that it always lies in an
> > STA. Its client, though, can have any apartment model. If
> > A makes a call on a different component say B, which
> > makes an out-of-proc call. Now if another call on A
> > arrives, it will go in (rerenter) the component A. So
> > what I have is TWO calls on A have gone in
> > simultaneously! So, the component A can no more safely
> > assume that it is safe and all calls on it are strictly
> > serialized. So it will have to make itself thread-safe.
> >
> > Is the above thought really true? If it is, then it
> > destroys the very basics of STA components not having to
> > worry about thread-safety.
>
> STA component is still thread safe in the sense that its
> methods cannot execute _simultaneously_. However,
> thread-safety doesn't imply protection from reentering.
> Whether to ensure call serialization is up to you. After
> all, until you avoid code that makes ORPC calls you can
> assume that execution flow is serialized. Alternatively, you
> can quard youself quite simply:
>
> HRESULT A::foo()
> {
> if(m_bCallPending)
> return E_PENDING;
>
> m_bCallPending = true; // member of A
>
> HRESULT hr = b.bar(); // call to out-of-proc server
>
> m_bCallPending = false;
>
> return hr;
> }
>
>
>