WCF service: how to always execute in same thread

L

ludwig_stuyck

Hi all,

I'm service enabling a single-threaded COM component, which has the
requirement thet everything is executed in the same thread. How can I
make sure that if a WCF service method is called, it is executed in
always the same thread?

Thanks!!
 
P

Peter Morris

add this to your webservice class

private static object SyncRoot = new object();

Whenever you call a method etc on this COM object you do this


lock (SyncRoot)
{
Do stuff here
}


It would be much better though if you were able to create multiple instances
of the COM object and it would allow many threads (but only one per
instance), otherwise this is potentially going to be a huge bottleneck in
your service.


Pete
 
M

Marc Gravell

Can't you just mark the service activation as singleton, synchronized?
Add this to your WCF-service class:

// might need to use ConcurrencyMode.Reentrant in some scenios
[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Single, //
single-threaded per instance
InstanceContextMode=InstanceContextMode.Single)] // singleton
instance

(and for the record, the "lock" answer only serializes; it doesn't
thread-switch)

Aside: WCF respects sync-context by default, so another way to do this
is to host WCF from a winform; although this is more a symptom of
winform than a sensible WCF answer!

Marc
 
W

Willy Denoyette [MVP]

Hi all,

I'm service enabling a single-threaded COM component, which has the
requirement thet everything is executed in the same thread. How can I
make sure that if a WCF service method is called, it is executed in
always the same thread?

Thanks!!


WCF threads run in the MTA, "Single Threaded" COM components need an STA
thread to run. That means that your "Single threaded" COM object will run on
the "default" process STA thread created by COM itself, all accesses to the
object will have to be marshaled from the MTA threads to the single STA
thread. This is especially bad because it doesn't scale, all accesses will
have to get serialized, but there is more, if your component is really
"Single", that is, your component is marked "Single" and not "apartment",
then it won't probably work as the component is not designed to be used in a
multi-threaded environment. I would suggest you to check this before going
any further with this.


Willy.
 
L

ludwig_stuyck

WCF threads run in the MTA, "Single Threaded" COM components need an STA
thread to run. That means that your "Single threaded" COM object will run on
the "default" process STA thread created by COM itself, all accesses to the
object will have to be marshaled from the MTA threads to the single STA
thread. This is especially bad because it doesn't scale, all accesses will
have to get serialized, but there is more, if your component is really
"Single", that is, your component is marked "Single" and not "apartment",
then it won't probably work as the component is not designed to be used in a
multi-threaded environment. I would suggest you to check this before going
any further with this.

Willy.

Hi all,

the COM component that needs to be service-enabled can only work in 1
thread. That means, the thread that creates the COM object is the only
thread where I can use this COM component. I can only create 1
instance of it. So what I did is: used the IDesign's sample to make
sure that every request is executed in the same thread; and making
sure that only 1 call at a time can execute. Because this is a
potential bottleneck, only fast COM calls are done this way. The calls
that take a while to complete will be queued to another server where a
second instance is running. (PS - I'm service enabling the Protean ERP
COM API)
 
W

Willy Denoyette [MVP]

Hi all,

the COM component that needs to be service-enabled can only work in 1
thread. That means, the thread that creates the COM object is the only
thread where I can use this COM component. I can only create 1
instance of it. So what I did is: used the IDesign's sample to make
sure that every request is executed in the same thread; and making
sure that only 1 call at a time can execute. Because this is a
potential bottleneck, only fast COM calls are done this way. The calls
that take a while to complete will be queued to another server where a
second instance is running. (PS - I'm service enabling the Protean ERP
COM API)


This doesn't answer the question about what type of COM object it is, with
this I mean what's his "apartment type"?
The apartment type can be found back in the registry or by using
OLEVIEW.EXE.
As apartment type you can have "Single", "Apartment", "Both" and "Free",
only both and Free can live in a MTA, the other need an STA thread to live
in.
Now, because all thread created by WCF will enter the MTA, the objects of
type single and Apartment will get instantiated on a COM managed STA thread
as there are no other STA thread is available in the service (WCF) process.
In this case, all accesses from the MTA threads will need to get marshaled
to the STA thread where the object lives. This marshaling requires two
important things:
1. The STA thread needs a message pump, WCF doesn't pump a message queue, so
you'll have to create a separate thread initialized to enter an STA and you
will have to provide the message pump.
2. The interface needs marshaling support from typelib marshaler, COM
objects of type "Single" don't have this marshaling, so they are not usable
in this context.

So this leaves you with only "apartment" and "both" COM types as usable,
provided they are created on a separate thread as in 1 above.
"Free" COM types will live on the callers thread in the MTA, that means each
client will have it's own COM instance which is not what you want.

Willy.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top