¿Debo usar un bloqueo para evitar un interbloqueo de WCF en esta situación?

I have a WCF duplex service with a 2 way method called GetList, plus a one way callback method ItemUpdated.

I've detected a deadlock in the following situation:

  1. The service calls the ItemUpdated callback, which is handled in the client by the method OnItemUpdated.
  2. Before the previous method returns, some user interaction causes the client to call GetList on the service.

I could set the ConcurrencyMode of my service to Reentrant, but that's not what I need. What I need is to make sure that my client is not processing any callback from the service before calling GetList.

So I can synclock an object to make sure that this doesn't happen. Is that my better alternative?

ACTUALIZACIÓN:

Just to clarify what my current design is, my service is actually a windows service that does some processing on a list of objects on a schedule and when each item is updated it raises the event ItemUpdated. This service has a WCF service facade that allows one or many consoles (clients) to subscribe to its events and see what is going on in the service.

preguntado el 30 de agosto de 12 a las 20:08

What are your ConcurrencyMode and InstanceMode now? -

In all likelihood, "locking" is only going to make things worse :) Words like "two way" and "duplex" are potentially scary - your service should be designed to be apátrida, if at all possible. Messages in both directions - sure. One thing on one host waiting on something from the other host: please revisit the protocol you've designed. Seguro look at ErnieL's response, and read the link he posted. It's good advice, IMHO... -

@paulsm4: I've updated my question to clarify my current design. As I mention there, my service is a windows service so it cannot really be stateless. Also, I don't see how two-way (as opposed to one-way) methods are scary. I'll concede that duplex services are harder to design and maintain, and how using them for a provider-subscriber pattern might be an arguable decision. -

2 Respuestas

InstanceContextMode = Single together with ConcurrencyMode = Single causes WCF to serialize all the calls to your single instance. In other words WCF has created a lock to enforce serialization. This is the cause of the deadlock. Adding yet another lock might work. But you are proposing a client lock... the client shouldn't have to change its threading behavior to keep the service from deadlocking. The service needs to be more robust than that.

This is a service issue. You should create a more robust service.

I would suggest changing the service to remove the serialization and prevent the possibility of deadlock entirely. My suggestion (in order that I would try):

  1. Change the service's InstanceContextMode to PerCall. The "preferred" design is to have the service be stateless. Create a different service instance for each call removes the forced serialization. Store all your state information in a common store (for example a database or cache).

  2. Have the service make the ItemUpdated callback on a different thread. This allows the service thread to complete before the callback is done. The problem with this solution is that if the ItemUpdated callback throws an exception the service is no longer waiting to catch and handle it. This means good error handling is harder.

Vea Descubra poderosas técnicas de administración de instancias para desarrollar aplicaciones WCF , para obtener más información.

Respondido 30 ago 12, 22:08

The problem was not really on the service but on the callback handler in my client. This is basically what was happening:

  1. My service raises an event that calls ItemUpdated on the client.
  2. While the callback is still processing ItemUpdated, the user forces GetList to be executed.
  3. The service receives the request and sends back the result of GetList, but my client cannot process the response from the service because it is already processing another callback.

So I ended up changing the ConcurrencyMode in the callback using the CallbackBehavior attribute. The service remains with ConcurrencyMode = Single.

Respondido 31 ago 12, 14:08

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.