29 votes

Silverlight 4.0 et proxy client WCF - comment créer et comment fermer des instances

Sujet de Silverlight, WCF proxy de service de cycle de vie n'est pas très clair pour moi. J'ai lu divers matériaux, des ressources, des réponses ici, mais je ne comprends pas complètement la supposée meilleure façon de les utiliser.

Je suis à l'aide personnalisée binaire de la liaison dans Silverlight 4.0 actuellement.

Est la création d'un proxy dans silverlight une opération coûteuse? Devrions-nous essayer de partager proxy exemple en code ou en créer de nouveau, c'est mieux? Devrions-nous faire de verrouillage si nous le faisons dans le cas où plusieurs threads accèdent il?

Depuis une erreur sur un proxy sera la faute de l'état d'un proxy je pense que le partage d'un proxy n'est pas une bonne idée, mais j'ai lu que la création est cher, donc ce n'est pas 100% clair que faire ici.

Et avec fermeture - silverlight, WCF service clients seulement fournir CloseAsync méthode. Aussi exiger que les procurations certaine logique à être utilisés quand ils sont fermés ( si elles sont défectueuses, nous devrions l'appeler Abort() qui est synchrone dans Silverlight et si nous devrions CloseAsync qui n'est pas synchrone, ou quoi?).

Dans de nombreux officiels échantillons de Silverlight à partir de MS procurations ne sont pas fermées que ce soit , est que tout défaut de matériaux ou devrait l'approche d'eux?

Le sujet est très important pour moi et je veux une compréhension claire de toutes les choses qui devraient être considérées dont je n'en ai pas.

( Je l'ai fait voir que cette question qu'est-Ce que le bon cycle de vie d'un service WCF client proxy dans Silverlight 3? semble proche de la mienne, mais je ne peux pas dire que je suis satisfait de la qualité des réponses)

J'aimerais vraiment voir un exemple de code qui utilise, crée , ferme etc proxys WCF, et le plus important qui explique, pourquoi c'est la meilleure manière possible. Je pense aussi (actuellement crois) qu'en raison de la nature du problème, il devrait y avoir qu'une seule utilisation de la meilleure pratique/modèle de l'approche à utiliser (créer,réutiliser,fermer) proxys WCF dans Silverlight.

8voto

Adam Jones Points 556

Résumé: je crois que la meilleure pratique consiste à instancier votre client de service web lorsque vous êtes sur le point de l'utiliser, puis le laisser aller hors de portée et obtenir des ordures collectées. Cela se reflète dans les échantillons de venir vous voir à partir de Microsoft. Justification suit...

Complet:La meilleure description complète du processus que j'ai trouvé est au Comment: Accéder à un Service de Silverlight. Ici, l'exemple montre le schéma typique de l'instanciation de la client de service web et permettant d'aller hors de portée (sans avoir besoin de le fermer). Des clients de services Web hériter de ClientBase qui a une méthode Finalize qui doit libérer toutes les ressources non managées, si nécessaire, lorsque l'objet est d'ordures collectées.

J'ai une quantité décente de l'expérience à l'aide de services web, et j'ai utiliser des proxys et les instancier droit avant de l'utiliser, puis de leur permettre d'être nettoyée. Je n'ai jamais eu un problème avec cette approche. J'ai lu sur Wenlong Dong Blog qui a dit que la création de la procuration était cher, mais encore, dit-il de la performance s'est améliorée .NET 3.5 (peut-être qu'il s'est encore amélioré depuis?). Ce que je peux vous dire est que la performance est un terme relatif, et à moins que vos données soient récupérées est moins trivial de taille, beaucoup plus de temps sera consacré à la sérialisation/désérialisation et des transports que la création de la connexion. Cela a certainement été mon expérience, et vous êtes mieux de l'optimisation dans ces domaines.

Dernier, depuis que j'ai la figure de mes opinions à ce jour est peut-être insuffisant, j'ai écrit un test rapide. J'ai créé un Silverlight web service en utilisant le gabarit fourni avec Visual Web Developer 2010 Express (avec, par défaut, une méthode void appelés DoWork()). Ensuite, dans mon exemple de client Silverlight je l'ai appelé en utilisant le code suivant:

int counter=0;
public void Test()
{
    ServiceReference1.Service1Client client = new ServiceReference1.Service1Client();
    client.DoWorkCompleted += (obj, args) => 
    { 
        counter++;
        if (counter > 9999)
        {
            for(int j=0;j<10;j++) GC.Collect();
            System.Windows.MessageBox.Show("Completed");
        }
    };
    client.DoWorkAsync();
}

J'ai alors appelé la méthode de Test à l'aide de for(int i=0;i<10000;i++) Test(); et tiré de l'application. Il a fallu un peu plus de 20 secondes pour charger l'application et remplissez les appels de service web (tous les 10 000 d'entre eux). Comme le service web d'appels ont été faits, j'ai vu l'utilisation de la mémoire pour le processus de sauter à plus de 150 MO, mais une fois que les appels réalisés et GC.Collect() a été appelé l'utilisation de la mémoire est tombé à moins de la moitié de cette somme. Loin d'être un parfait test il me semble me confirmer qu'aucune mémoire ne fuyait, ou il a été négligeable (en considérant qu'il est sans doute assez rare, à l'appel de 10 000 appels de service web tout en utilisant séparer les instances de client). Aussi c'est un modèle plus simple que de garder un objet proxy et avoir à vous soucier de failles et d'avoir à les rouvrir.

La Justification de la Méthodologie de l'Essai: Mon test axé sur les 2 problèmes potentiels. L'un est une fuite de mémoire, et l'autre est le processeur le temps passé à créer et à détruire les objets. Ma recommandation est qu'il est sûr de suivre les exemples fournis par la société (Microsoft) qui fournit les classes. Si vous êtes préoccupé par l'efficacité du réseau, alors vous devriez avoir aucun problème avec mon exemple dans la mesure correctement la création/l'élimination de ces objets ne serait pas l'effet de la latence du réseau. Si 99% du temps passé est l'heure du réseau, puis optimisation pour l'un théorique, l'amélioration dans le 1% est probablement un gaspillage en termes de temps de développement(en supposant qu'il est même un avantage à gagner qui, je crois, mon test montre clairement qu'il y a peu/aucun). Oui, la mise en réseau des appels locaux c'est à dire qu'au cours des 10 000 appels de service, seulement environ 20 secondes sera passé à attendre pour les objets. Qui représente environ 2 millisecondes par appel de service consacré à la création de ces objets. Quant à la nécessité de Disposer d'appel, je ne veux pas laisser entendre que vous ne devriez pas l'appeler, mais simplement qu'il ne semble pas nécessaire. Si vous oubliez (ou tout simplement choisir de ne pas), mes tests m'ont amené à croire que d'Aliéner a été appelé dans le Finaliser pour ces objets. De même, il serait probablement plus efficace d'appeler Disposer vous-même, mais encore l'effet est négligeable. Pour la plupart des logiciels de développement, vous obtenez plus de gains de venir avec plus d'efficacité des algorithmes et structures de données que par languir plus de ces questions (sauf si il y a une grave fuite de mémoire). Si vous avez besoin de plus d'efficacité, alors peut-être vous ne devriez pas être en utilisant les services web comme il y a plus efficace des données options de transport en commun qu'un système qui est basé sur XML.

0voto

Kit Points 4632

La création de Proxy n'est pas cher par rapport à l'appel de l'aller-retour. J'ai vu un commentaire qui dit d'appeler CloseAsync immédiatement après votre appel à d'autres méthodes asynchrones, mais qui semble être défectueux. En théorie, la proximité se déplace dans un état d'attente qui se passe après vos autres appels asynchrones fin. Dans la pratique, j'ai vu les appels à la fin avec une rapidité surprenante, avec une faute, et puis l' CloseAsync lui-même les défauts parce que le canal a déjà reproché.

Ce que j'ai fait est de créer un générique Caller<TResult> classe qui a un certain nombre de CallAsync méthode générique des surcharges qui acceptent des arguments et un rappel de type Action<TResult>. Sous les couvertures, l' Caller seraient fil de l' XxxCompleted événement et vérifier pour voir si la raison de l'achèvement était due à une erreur ou pas. En cas d'erreur, il Abort le canal. Si pas d'erreur, il s'agirait CloseAsync puis d'appeler la fonction de rappel. Cela empêche "bêtement" des erreurs, comme par exemple essayer d'utiliser le canal dans l'état faulted.

Tout ce qui précède suppose de créer un-proxy-faire-appel-rejet-utilisation-de-proxy modèle. Si vous aviez à faire de nombreux appels en succession rapide, vous pouvez adapter cette approche à compter le nombre de vol les appels et à la toute fin de la dernière, ne la fermez ou abandonner ensuite.

Il est probable qu'il est rare que la création de proxy surcharge sur un par appel ou par un ensemble d'appels va être un problème. Seulement si la charge est trop élevée aurais-je poursuivre un proxy de mise en cache ou la réutilisation de la stratégie. Rappelez-vous, le plus vous maintenez une ressource, plus le risque de la panne. Dans mon expérience, au moins, la plus courte de la durée de vie, le meilleur de la performance perçue par l'utilisateur, car vous interrompre pour lui/elle au moins, vous n'avez pas besoin de coûteux à maintenir la logique de nouvelle tentative (ou au moins moins que ça), et vous êtes de plus en plus confiant que vous n'êtes pas une fuite de mémoire ou de ressources en sachant précisément quand se débarrasser d'eux.

En ce qui concerne votre question sur les exemples ne ferme pas... eh bien, ceux sont des exemples, et sont généralement à une dimension et incomplète parce qu'ils sont l'illustration d'un usage général, pas tous les détails à propos de ce que vous devez faire à travers une application entière de la vie.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X