Bonne question. Avant que l'application cliente n'appelle une méthode, elle ouvre le canal. Le canal est utilisé pour toutes les communications de données. Il y a deux manières d'envoyer: 1) session fiable - quand vos paquets sont désendettés de manière fiable et les paquets fissurés sont renvoyés, 2) commande - quand les demandes sur le service sont calculées dans l'ordre où ils ont été transférés du client (pas comment ils sont livrés) . Si vous avez une session ordonnée fiable et que l'hôte de service rencontre des problèmes avec vos données après la fermeture de l'application, l'hôte essaiera de demander au client de renvoyer les données et après aucune réponse, rejettera tout ce que vous demanderez. Dans une autre situation (non fiable) après l'ouverture du canal, vous pouvez envoyer des données et détruire la communication, la méthode oneway calculera votre demande, s'il n'y aura pas d'exception.
Pour tester certaines possibilités avec le problème de service (pas exactement votre client paroblem est cependant utile) créer une solution:
1) projet de bibliothèque "WcfContracts" avec un fichier "IService1.cs":
[ServiceContract]
public interface IService1
{
[OperationContract]
void ThrowException();
[OperationContract(IsOneWay=true)]
void ThrowExceptionUseIsOneWay();
}
2) projet Console "WcfConsoleHoster" qui a deux "référence WcfContracts", et se compose des trois fichiers:
a) Service1.cs, qui est mise en œuvre de services
public class Service1 : WcfContracts.IService1
{
public void ThrowException()
{
throw new Exception("Basic exception");
}
public void ThrowExceptionUseIsOneWay()
{
throw new Exception("Basic exception using IsOneWay=true");
}
}
b) Program.cs, qui a un point d'entrée par défaut et commence juste le service
static void Main(string[] args)
{
ServiceHost host = new ServiceHost(typeof(Service1));
host.Open();
Console.WriteLine("host 1 opened");
Console.ReadKey();
}
c) service "App.config"
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<services>
<service behaviorConfiguration="behavourHttpGet" name="WcfConsoleHoster.Service1">
<host>
<baseAddresses>
<add baseAddress="http://localhost:8732/Design_Time_Addresses/WcfConsoleHoster/Service1/" />
</baseAddresses>
</host>
<endpoint binding="wsHttpBinding" contract="WcfContracts.IService1" />
<endpoint address ="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="behavourHttpGet">
<serviceMetadata httpGetEnabled="true" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
3) projet Console "WcfConsoleClient" , qui appelle simplement le service
a) Dans "Program.cs"
Console.WriteLine("Wcf client. Press any key to start");
Console.ReadKey();
ChannelFactory<IService1> factory = new ChannelFactory<IService1>("Service1_Endpoint");
IService1 channel = factory.CreateChannel();
//Call service method
channel.ThrowException();
Console.WriteLine("Operation executed");
Console.ReadKey();
b) Client "App.config"
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<client>
<endpoint name="Service1_Endpoint"
address="http://localhost:8732/Design_Time_Addresses/WcfConsoleHoster/Service1/"
binding="wsHttpBinding"
contract="WcfContracts.IService1">
</endpoint>
</client>
</system.serviceModel>
</configuration>
1. Exception Throwing. D'abord, nous appelons la méthode bidirectionnelle qui déclenche une exception dans l'hôte du serveur. Puis cette exception revient au client et le canal l'élève du côté client, l'application est détruite. Bien sûr, vous pouvez gérer cela avec try() catch {} block.
Regardons la même chose avec méthode unidirectionnelle en appelant channel.ThrowExceptionUseIsOneWay();
. L'exception est déclenchée dans l'hôte de service, mais il n'y a pas d'exception côté client et l'opération est exécutée. Il est important de réaliser que le canal sera indisponible pour la prochaine utilisation.
Donc, IsOneWay=true
fonctionne comme prévu - il envoie un message seulement d'une manière. Vous ne pouvez pas retourner un objet de la méthode (void est attendu) et vous ne pouvez pas utiliser FaultContract ou obtenir InvalidOperationException après le démarrage du service.
2. Thread.Sleep(). Le test suivant est en opération massive avec Thread.Sleep()
. IService1
est étendu à
[OperationContract]
int ThreadSleep();
[OperationContract(IsOneWay=true)]
et la réalisation en Service1.cs est en attente pendant 5 secondes
public int ThreadSleep()
{
System.Threading.Thread.Sleep(TimeSpan.FromSeconds(5));
return 1;
}
public void ThreadSleepUseIsOneWay()
{
System.Threading.Thread.Sleep(TimeSpan.FromSeconds(5));
}
maintenant une modification de bit pour le client pour le comptage écoulé le temps d'appel
System.Diagnostics.Stopwatch stopwatch = new System.Diagnostics.Stopwatch();
stopwatch.Start();
//call methode
channel.ThreadSleep();
stopwatch.Stop();
Console.WriteLine(string.Format("Operation executed in {0} seconds", stopwatch.Elapsed.Seconds));
Console.ReadKey();
Appel deux méthode de façonThreadSleep()
a le résultat « opération exécutée en 7 secondes "(5 secondes pour le sommeil du thread + 2 secondes pour l'initialisation du canal).
One way method
avec l'appel channel.ThreadSleepUseIsOneWay()
a comme résultat "0 secondes"! Il n'y a pas d'attente pour la réponse du service!
Il est préférable d'utiliser NetNamedPipeBinding, qui est une connexion fiable et rapide sur la même machine.
Je sais que je ne peux pas m'assurer que la méthode sera appelée au service (reçu) et c'est ok. Parce que c'est sur la même machine, je crois que c'est assez fiable pour être toujours reçu. Cependant, comment puis-je m'assurer que le client envoie le message d'appel de la méthode? et aussi garder la méthode à sens unique? –