2010-02-02 7 views
2

Je travaille sur une application n-tier en utilisant WCF entre les couches telles que:n-Tier WCF (question Threading?) Fiable

Niveau 1: application Silverlight Invoque la requête de recherche

 IClientBroker clientBroker = UIContext.CreateWcfInterface<IClientBroker>("Data/ClientBroker.svc"); 
     clientBroker.BeginSearchForClients(SearchTerm, 20, (result) => 
     { 
      SearchResult[] results = ((IClientBroker)result.AsyncState).EndSearchForClients(result).ToArray(); 

      // do stuff, update UI, etc. 

     }, clientBroker); 

Niveau 2: service Web WCF utilisant basicHttp pour appeler Silverlight. Ceci agit comme un proxy au 3ème niveau.

[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)] 
class ClientBroker : IClientBroker 
{ 
      [OperationContract] // as defined in IClientBroker 
    public SearchResult[] SearchForClients(string keywords, int? maxResults) 
    { 
     ClientBrokerClient clientBroker = CreateClientBrokerClient(); 

     SearchResult[] searchResults=clientBroker.SearchForClients(keywords, maxResults); 
     return searchResults; 
    } 
    } 

Niveau 3: est le « serveur » dans la mesure où cela offre un point de terminaison net.tcp (permettant aux clients de se connecter sans sécurité à l'aide de Silverlight). C'est la cible ultime d'une demande.

public class ClientBroker : IClientBroker // note this is different to tier 2 interface 
    { 

     public SearchResult[] SearchForClients(string keywords, int? maxResults) 
     { 
        // do stuff 
      if (maxResults.HasValue) 
      { 
       return results.Take(maxResults.Value).ToArray(); 
      } 
      else 
      { 
       return results.ToArray(); 
      } 
     } 
    } 

Alors mes appels aller:

Silverlight ->HTTPBasic -> IIS-service hébergé proxy WCF ->net.tcp -> service WCF hébergé EXE-

Cela fonctionne bien. Je peux passer des en-têtes à travers les calques, et maintenir des sessions, etc. Et c'est très équilibré. MAIS cela ne prend que quelques appels pour provoquer un timeout dans la communication.

Le temps que le serveur-EXE prend pour faire son travail est négligeable. Le problème que je vois est que le serveur "fige" dans le renvoi des résultats au niveau 2.

Je pense que cela a à voir avec un thread qui se verrouille.

J'ai regardé autour et voir que la meilleure façon de le faire est de faire mon niveau 2 run asyncronously, similaire au code ci-dessous:

public SearchResult[] SearchForClients(string keywords, int? maxResults) 
    { 
     ClientBrokerClient clientBroker = CreateClientBrokerClient(); 
     clientBroker.BeginSearchForClients(keywords, maxResults, result => 
      { 
       SearchResult[] searchResults=((ClientBrokerClient)result.AsyncState).EndSearchForClients(result); 
       // how to return results from here? 
      }, clientBroker); 

    } 

Mais comment puis-je obtenir quand mon niveau 1 le client attend le résultat de cette méthode, qui va juste tomber directement avant que le rappel s'exécute? Est-ce que je manque quelque chose sur ma construction de mes méthodes OperationContract?

MISE À JOUR:

J'ai depuis mis mon serveur (niveau 3) à l'épreuve d'un client en évitant de niveau 2 en faisant de nombreuses demandes de lui. Semble le canal WCF net.tcp pour le niveau 3 est solide comme le roc.

MISE À JOUR 2:

Ce blog décrit en utilisant le modèle IAsyncResult, que j'ai échappé ici. Est-ce que j'aboie le mauvais arbre ici? http://blogs.msdn.com/wenlong/archive/2009/02/09/scale-wcf-application-better-with-asynchronous-programming.aspx

MISE À JOUR 3:

Ok, ce paragraphe de ce blog:

« Si vous construisez des services N-tier WCF , vous auriez service WCF opérations invoquant des proxies client WCF pour d'autres services backend.Dans ce cas , vous devez vous assurer que le niveau intermédiaire (couche de routage) a opération de service asynchrone invoquant les opérations asynchrones WCF proxy . De cette façon, votre niveau intermédiaire ne va pas manquer de fils lors du traitement de nombreuses opérations lentes. »

semble confirmer mes soupçons que le problème réside dans la couche intermédiaire (niveau 2). Comment J'obtiens cet asynchronisme Begin/End? Est-ce que je dois le faire manuellement ou puis-je conserver les outils VS pour générer les classes de proxy pour moi? (VRAIMENT ne pas avoir à le faire manuellement, les contrats ont un certain degré de flux dans . les)

Répondre

0

Eh bien, je pense que je l'ai résolu ce sujet m'a aidé:

wcf service stops after few requests

Fondamentalement, je n'avais pas fermé mes proxies clients dans mon niveau 2, ce qui, je le sais, provoquerait un blocage. L'évolution du code était telle que j'ai fini par supprimer les blocs utilisant() {} pour faciliter les exceptions qui ne sont pas éteintes avec le proxy client. Cependant, je l'ai restructuré et retestés et mon niveau 2 code ressemble maintenant à:

public SearchResult[] SearchForClients(string keywords, int? maxResults) 
    { 
     ClientBrokerClient clientBroker = CreateClientBrokerClient(); 

     SearchResult[] searchResults=clientBroker.SearchForClients(keywords, maxResults); 
     clientBroker.Close(); 
     return searchResults; 
    } 

... et les exceptions ne sont pas éteintes.