Question

Je conçois une application de discussion client-serveur (en fait, je ne le suis pas, mais supposons que je le suis :)), et je suis un peu perplexe devant certaines conditions de compétition que j'ai connues.

Disons que j'ai le code suivant:

public interface IServer
{
  [OperationContract(IsOneWay = false)]
  [FaultContract(typeof(ChatException))]
  void BroadcastMessage(string msg);
}

public class Server : IServer 
{
  void BroadcastMessage(string msg) // I'm not mentionning the try/catch/throw FaultException here for readability purposes
  {
    foreach (IClientCallback c in callbacks){
      c.ReceiveMessage(msg);
    }

  }
}

public interface IClientCallback
{
  [OperationContract(IsOneWay = true)]
  void ReceiveMessage(string s);
}

Et voici un extrait de la configuration de la liaison:

<endpoint address="" 
binding="netTcpBinding" 
bindingConfiguration="DuplexBinding" 
contract="IServer" />

 <binding name="DuplexBinding" sendTimeout="00:01:00">
   <reliableSession ordered="true" inactivityTimeout="00:05:00" enabled="true"/>
   <security mode="None">
     <transport clientCredentialType="Windows" protectionLevel="EncryptAndSign" />
     <message clientCredentialType="Windows" />
   </security>
 </binding>

C’est bien sûr une sorte de pseudo c #, j’ai retiré beaucoup de code non pertinent pour plus de clarté.

Maintenant au but: Ce code ne fonctionnera pas. Lorsque j'appelle BroadcastMessage, la méthode ne revient jamais et j'ai éventuellement un délai d'expiration du côté client. Si je débogue côté serveur, tout semble aller pour le mieux (je retourne de la méthode BroadcastMessage exactement comme on pourrait s'y attendre, et je ne bloque aucun appel à sens unique de ReceiveMessage)

Voici deux façons de corriger ce code:

  1. supprimez FaultContract et déclarez la méthode BroadcastMessage comme oneway = true
  2. Diffusez le message à tout le monde MAIS l'expéditeur initial

Ma première hypothèse était que le côté client attendait le retour du serveur et n'était donc pas disponible pour gérer l'appel entrant ReceiveMessage depuis le serveur, bloquant ainsi le serveur. Le serveur montre qu'il ne bloque aucun appel à ReceiveMessage

Maintenant, mes questions:

  • Que se passe-t-il?

  • Existe-t-il d'autres moyens de résoudre ce problème? (peut-être en ajustant la configuration de la liaison?)

  • Supposons que je choisis le correctif 2 (c.-à-d. que je ne renvoie pas à l'expéditeur), que se passe-t-il si le serveur appelle mon rappel ReceiveMessage (parce que quelqu'un d'autre m'a envoyé un message) pendant que j'attends le mien? Appel BroadcastMessage à terminer?

  • J'ai lu que les appels OneWay ne sont pas totalement à sens unique et que le serveur attend toujours une réponse HTTP de l'autre côté. Des détails à ce sujet? Plus précisément, le client est-il en mesure de répondre aux réponses http du serveur quand il est bloqué lors d’un appel distant?

Edition: Console .net 3.5 côté serveur, Winforms .net 3.5 côté client

Était-ce utile?

La solution

Cela ressemble à une impasse, peut-être en raison du contexte de synchronisation. Quel est le client? Winform? WPF? WCF respecte le contexte de synchronisation, ce qui signifie "basculer vers le fil de l'interface utilisateur". pour winforms et WPF. Si vous faites la demande de blocage sur le fil de l'interface utilisateur, le jeu est terminé.

Essayez d’exécuter votre requête WCF sur un thread d’arrière-plan afin que le thread d’UI soit disponible pour traiter la requête entrante; Cela pourrait être aussi simple que d'utiliser ThreadPool ou peut-être BackgroundWorker .

Autres conseils

essayez d'ajouter cet attribut à votre implémentation concrète de votre service:

[System.ServiceModel.ServiceBehavior(UseSynchronizationContext=false)]
public class Server : IServer {}

Deuxièmement, essayez d'activer le traçage WCF pour voir si quelque chose se passe dans les entrailles de votre implémentation WCF qui donne du chagrin à votre âme. J'ai eu des erreurs très étranges qui n'avaient de sens que lorsque je suis entré dans le traçage et que j'ai découvert le message d'erreur RÉEL qui se produisait.

Suivi d'un service WCF

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top