Je concevais une application de chat client-serveur (en fait je ne suis pas, mais prétendons que je suis :)), et je suis un peu déconcerté par certaines conditions de course J'ai expérimenté.conditions de course dans WCF avec des méthodes non-oneway
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 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>
Ceci est bien sûr une sorte de pseudo C#, je Nous avons supprimé beaucoup de code non pertinent pour des raisons de clarté.
Maintenant au point: Ce code ne fonctionnera pas. Lorsque j'appelle BroadcastMessage, la méthode ne revient jamais et j'obtiens finalement un délai d'expiration côté client. Si je débogue sur le côté serveur, tout semble bien (je reviens de la méthode BroadcastMessage exactement comme on s'y attend, et je ne bloque pas sur les appels unidirectionnels ReceiveMessage)
Voici deux façons de corriger ce code:
- retirer le FaultContract et déclarer la méthode BroadcastMessage comme oneway = true
- diffusion du message à tout le monde, mais l'expéditeur initial
Ma première hypothèse est que le côté client attendait le serveur revenir , et n'était donc pas disponible pour gérer l'appel entrant ReceiveMessage du serveur, bloquant ainsi le serveur, BUT ReceiveMessage est déclaré comme unway, et le débogage du serveur montre qu'il ne bloque pas sur un appel à ReceiveMessage
Maintenant , mes questions:
Que se passe-t-il?
Y a-t-il d'autres moyens de résoudre ce problème? (Peut-être en réglant la configuration de liaison?)
Disons que je choisis fix 2 (ie ne diffuse pas à l'expéditeur), ce qui se passe si le serveur appelle mon rappel ReceiveMessage (parce que quelqu'un d'autre m'a envoyé un message) pendant que j'attends que mon propre appel BroadcastMessage se termine? J'ai lu que les appels OneWay ne sont pas totalement unilatéraux, 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 capable de répondre aux réponses HTTP lorsque celles-ci sont bloquées dans un appel distant?
Edit: Console .net 3.5 sur le côté serveur, Winforms 3.5 .net sur le côté client
En effet, je fais mon appel de l'interface utilisateur Thread.I'll essayer inovking sur l'autre. Pourtant, je ne comprends pas pourquoi l'impasse se produit. Le serveur ne devrait pas attendre que le client réponde, devrait-il? Pourriez-vous être plus précis sur ce qui se passe derrière la scène ici? Merci beaucoup! – Brann
Vous avez un sens = faux ... donc * devrait * attendre. –
Invoquer à partir d'un autre thread a résolu le problème! :) – Brann