WCF, Smart Clients, and Deadlocks
Friday, April 11th, 2008.There’s a new article up on MSDN describing how to write Smart Clients using WCF. The author is none other than WCF-Master Lowy and he goes over the multitude of ways you can deadlock yourself.
Here’s a taste:
UI Thread and Concurrency Management
Whenever you use hosting on the UI thread, deadlocks are possible. For example, the following setup is guaranteed to result with a deadlock: A Windows Forms application is hosting a service with UseSynchronizationContext set to true, and UI thread affinity is established. The Windows Forms application then calls the service over one of its endpoints. The call to the service blocks the UI thread, while WCF posts a message to the UI thread to invoke the service. That message is never processed, because of the blocking UI thread—hence, the deadlock.
Another possible case for a deadlock occurs when a Windows Forms application is hosting a service with UseSynchronizationContext set to true and UI thread affinity is established. The service receives a call from a remote client. That call is marshaled to the UI thread and is eventually executed on that thread. If the service is allowed to call out to another service, that can result in a deadlock if the callout causality tries somehow to update the UI or call back to the service’s endpoint, because all of the service instances that are associated with any endpoint (regardless of the service-instancing mode) share the same UI thread.
Similarly, you risk a deadlock if the service is configured for reentrancy and it calls back to its client. You risk a deadlock if the callback causality tries to update the UI or enter the service, because that reentrance must be marshaled to the blocked UI thread.
Actually, I have difficulty believing that Juval would go so far as to suggest that even the forms should be services, but he does:
Form as a Service
The main motivation for hosting a WCF service on the UI thread is if the service must update the UI or the form. The problem is always: How does the service reach out and obtain a reference to the form? While the techniques and ideas that appear thus far in the listings certainly work, it would be simpler yet if the form were the service and hosted itself. For this to work, the form (or any window) must be a singleton service. The reason is that singleton is the only instancing mode that enables you to provide WCF with a live instance to host. In addition, you would not want a per-call form that exists only during a client call (which is usually very brief), nor would you want a per-session form that only a single client can establish a session with and update.
When a form is also a service, having that form as a singleton service is the best instancing mode all around.
I think that this article serves as a great treatise leading to only one conclusion - you’d have to be crazy to try to do this without some higher level framework, preferably with a different low-level framework too
. Sucks Microsoft didn’t put one out - nor is there a pending beta, CTP, or even word about some project with a codename handling this. From what I know about Prism, it doesn’t intend to handle this issue either.
One thing that isn’t covered in the article is that if you do choose not to tie the client-side service to the UI thread, you open yourself up to race conditions. Reasons you’d want to handle messages on a different thread center around UI responsiveness. I’ve written about these things before:
-
Object Builder - the place to fix system-wide threading bugs
-
Eureka! AOP is the final piece of the multi-threaded smart client puzzle
-
What Makes Smart Clients Safe?
The more I read things like this, the more I feel that I have to get going with my nServiceBus based solution. I’m fairly swamped as it is, so if anyone is interested in helping get this project off the ground, I’d be most grateful - as I think anyone else that had to build a smart client would.
|
If you liked this article, you might also like articles in these categories:
If you've got a minute, you might enjoy taking a look at some of my best articles.I've gone through the hundreds of articles I've written over the past 4 years and put together a list of the best ones as ranked by my 2000+ readers. You won't be disappointed. If you'd like to get new articles sent to you when they're published, it's easy and free.Subscribe right here. Something on your mind? Got a question? I'd be thrilled to hear it. Leave a comment below or email me, whatever works for you. 2 CommentsYour comment... |







August 8th, 2008 at 5:26 am
Sorry, but Services should NOT have a user interface to begin with. If it needs to log information it should do so in a file with an exclusive write and shared read and then have another interface that interacts with that file. Even if I have to host in a UI app, I can use a different thread. This is server 101. I can’t believe I’m reading this.
August 9th, 2008 at 3:33 pm
Joe - I think that the motivation is race conditions and deadlocks in the UI when interacting with a service (not logging); not that I agree with the solution.