2010-04-01 8 views
0

J'ai un service WCF (le même) qui s'exécute sur plusieurs serveurs, et je voudrais appeler toutes les instances en parallèle à partir d'un seul client. J'utilise ChannelFactory et l'interface (contrat) pour appeler le service. Chaque service a un client local <endpoint> défini dans le fichier .config. Ce que j'essaye de faire est de construire une sorte de cadre générique pour éviter la duplication de code.Appels WCF parallèles sur plusieurs serveurs

Par exemple, un appel synchrone dans un seul thread ressemble à quelque chose comme ceci:

Dim remoteName As String = "endpointName1" 
    Dim svcProxy As ChannelFactory(Of IMyService) = New ChannelFactory(Of IMyService)(remoteName) 
    Try 
     svcProxy.Open() 
     Dim svc As IMyService = svcProxy.CreateChannel() 
     nodeResult = svc.TestRemote("foo") 
    Finally 
     svcProxy.Close() 
    End Try 

La partie que je vais avoir du mal à comment spécifier et appeler en fait la méthode à distance réelle (par exemple « TestRemote ») sans avoir à dupliquer le code ci-dessus, et toutes les choses liées au thread qui invoquent cela, pour chaque méthode.

En fin de compte, je voudrais être en mesure d'écrire du code le long des lignes de (considérer ce pseudo-code):

Dim results as Dictionary(Of Node, ExpectedReturnType) 
results = ParallelInvoke(IMyService.SomeMethod, parameter1, parameter2) 

où ParallelInvoke() prendra la méthode comme argument, aussi bien comme les paramètres (paramArray ou object() .. quel que soit), puis allez exécuter la requête sur chaque nœud distant, bloquer jusqu'à ce qu'ils retournent tous une réponse ou un délai, puis renvoyer les résultats dans un dictionnaire avec la clé comme nœud, et la valeur comme n'importe quelle valeur renvoyée.

Je peux ensuite (selon la méthode) choisir la seule valeur que j'ai besoin, ou agréger toutes les valeurs de chaque serveur ensemble, etc.

Je suis sûr que je peux le faire en utilisant la réflexion et InvokeMember(), mais cela nécessite de passer la méthode sous la forme d'une chaîne (ce qui peut conduire à des erreurs comme appeler une méthode non existante qui ne peut pas être interceptée à la compilation), donc j'aimerais voir s'il existe une méthode plus propre fais ceci.

Merci

+1

Vous ne savez pas exactement ce que vous voulez faire, mais vous pouvez examiner les proxies côté client générés par svcutil WCF et vous verrez comment vous pouvez programmer à un niveau inférieur pour appeler des services en passant des noms comme "TestRemote". Si vous voulez spécifiquement éviter cela, utiliser la réflexion fonctionnera, et cela ne nécessite pas de passer des chaînes littérales.vous pouvez interroger le proxy côté client pour voir quelles méthodes sont disponibles et les appeler de cette façon. – Cheeso

Répondre

3
public static TResult MakeCall<TService, TResult>(Func<TService, TResult> method, string remoteName) 
     { 
      // try not to create the factory object for each call, it can be a singleton 
      var factory = GetFactory<TService>(remoteName); 
      TService proxy = default(TService); 
      TResult result = default(TResult); 
      try 
      { 
       proxy = factory.CreateChannel(); 
       result = method(proxy); 
      } 
      finally 
      { 
       // proxy disposal is a bit tricky in WCF and you might need to read more about Close/Abort 
       Close(proxy);      

      } 
      return result; 
     } 

qui vous permet d'appeler n'importe quelle méthode sur n'importe quelle interface sans avoir à dupliquer le code de plomberie.

public interface IMyService 
     { 
      int Sum(int a, int b); 
      int Max(int a, int b); 
     } 

interface publique IMyService2 { Test bool (valeur de chaîne); }

static void Main(string[] args) 
     { 
      var a = 12; 
      var b = 12; 
      var r1 = MakeCall((IMyService proxy) => proxy.Sum(a, b), "endpoint1"); 
      var a1 = 12; 
      var b1 = 14; 
      var r2 = MakeCall((IMyService proxy) => proxy.Max(a1, b1), "endpoint1"); 
      var r3 = MakeCall((IMyService2 proxy) => proxy.Test("test"), "endpoint2"); 
     } 

Vous pouvez utiliser MakeCall comme bloc de construction pour votre solution finale.

1

Une façon de le faire est d'utiliser:

System.Threading.ThreadPool.QueueUserWorkItem (...)

Regardez ici pour la syntaxe VB: http://msdn.microsoft.com/en-us/library/4yd16hza.aspx

Placez le code aysnc dans WaitCallback.

+0

Cela se trouverait dans la méthode ParallelInvoke() dans mon exemple ci-dessus - mais n'aide pas à choisir quelle méthode (par exemple, TestRemote()) sans avoir à dupliquer tout le code environnant pour chaque méthode. – gregmac

+0

Oui, vous avez raison, je n'ai pas répondu à toutes vos questions. Voir le commentaire de Cheeso ci-dessus pour la réponse réelle. –

Questions connexes