WCF -Inproc: Client and Server on main thread -> Client call hangs...

J

José Joye

I'm currently running some tests with WCF in In-proc environment.

I have created a small winform application that starts the host in the main
thread with an named pipe endpoint.

If I call a method exposed by the server using the proxy from a separate
thread, all is fine. However, if I do the same from the main thread, the
call hangs and I get a timeoutException after 1min (default call timeout).

Can anyone explain me why this hangs in the second situation?

Thanks a lot!
- José
 
N

Nicholas Paldino [.NET/C# MVP]

Jose,

How did you enable thread affinity with the server on the main thread?
From what I understand, WCF services will process incoming requests on other
threads, not necessarily the thread that the ServiceHost is created on.

Could you post a complete example?
 
M

Marc Gravell

When you say "in-proc" - do you mean that you are hosting both the
service and client in the same winform process? If so, is the server
code /also/ talking to the form? If so, and you are using
Control.Invoke in the server code (to access UI elements), then you
have probably deadlocked yourself - as your UI code is probably
blocking the UI thread waiting for its method to complete.
This would also explain why calling the proxy method on a background
thread doesn't cause the issue: the UI thread isn't blocked, so your
server code can successfully use Control.Invoke.

Have I joined the dots? or missed by a mile?

Marc
 
M

Marc Gravell

And for info - in this scenario your best bet is probably to either
design around it (so your server doesn't need to talk to the UI), or
do what you're already doing: call the proxy from another (pool?)
thread, then use Control.BeginInvoke to marshal the result back to the
UI.

Marc
 
J

José Joye

Marc,

Thanks for your remark. This really makes sense. However, my server method
does not access the UI.

I have posted a sample of my problem within this thread (by the way, I have
just seen that the "catch section" for the method running in the 2nd thread
is buggy in my posted sample)

Thanks,
- José
 
N

Nicholas Paldino [.NET/C# MVP]

This is because you are creating a ServiceHost on the UI form. There is
a SynchronizationContext associated with the UI thread, and WCF picks up on
that. Because of that, all calls are routed to the UI thread. Because you
make the proxy call on the UI thread, you block yourself.

There is some more information on this situation here:

http://www.softinsight.com/bnoyes/PermaLink.aspx?guid=4bea53fa-2553-4d7b-bfe2-b0f0e9d11d0a

To get around this, on the implementation of your service, apply the
ServiceBehavior attribute, setting the UseSynchronizationContext to false
(it defaults to true). Either that, or set it in the config file.

Or, you can host the service, or make the call from the proxy on another
thread.

--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

José Joye said:
Nicholas,

I built a small sample.
See attached

- José
Nicholas Paldino said:
Jose,

How did you enable thread affinity with the server on the main thread?
From what I understand, WCF services will process incoming requests on
other threads, not necessarily the thread that the ServiceHost is created
on.

Could you post a complete example?


--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

José Joye said:
I'm currently running some tests with WCF in In-proc environment.

I have created a small winform application that starts the host in the
main thread with an named pipe endpoint.

If I call a method exposed by the server using the proxy from a separate
thread, all is fine. However, if I do the same from the main thread, the
call hangs and I get a timeoutException after 1min (default call
timeout).

Can anyone explain me why this hangs in the second situation?

Thanks a lot!
- José
 
N

Nicholas Paldino [.NET/C# MVP]

That's the thing, your server method does access the UI, just
unknowingly. Because you create the ServiceHost on a thread that has a
SynchronizationContext associated with it, the ServiceHost marshals all
calls through that SynchronizationContext to the UI thread.
 
M

Marc Gravell

There is a SynchronizationContext associated with the UI thread, and WCF picks up on
that. Because of that, all calls are routed to the UI thread.

Interesting; I hadn't thought of that (but then, I tend to stick to
simple service apps); I assumesd it would still be using its own
private threads. Thanks Nicholas; as a WCF user I'll squirrel that
knowledge away - it may be useful.

Always a pleasure,

Marc
 
N

Nicholas Paldino [.NET/C# MVP]

Marc,

To clarify, the ServiceHost does use its own threads to listen for the
incoming requests. However, when it comes time to actually dispatch the
call, if there was a SynchronizationContext associated with the creation of
the ServiceHost, the runtime will call the Send method on the
SynchronizationContext, dispatching the call.

In this case, it is a Windows Forms app, which marshals the call to the
UI thread. However, because the client of the service is blocking on the
call in the UI thread already, nothing gets processed. Classic deadlock
situation.
 
J

José Joye

Thanks a lot!

Nicholas Paldino said:
Marc,

To clarify, the ServiceHost does use its own threads to listen for the
incoming requests. However, when it comes time to actually dispatch the
call, if there was a SynchronizationContext associated with the creation of
the ServiceHost, the runtime will call the Send method on the
SynchronizationContext, dispatching the call.

In this case, it is a Windows Forms app, which marshals the call to the
UI thread. However, because the client of the service is blocking on the
call in the UI thread already, nothing gets processed. Classic deadlock
situation.


--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

Marc Gravell said:
Interesting; I hadn't thought of that (but then, I tend to stick to
simple service apps); I assumesd it would still be using its own
private threads. Thanks Nicholas; as a WCF user I'll squirrel that
knowledge away - it may be useful.

Always a pleasure,

Marc
 

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