2011-04-07 4 views
1

Comment gérer une exception levée dans une méthode de rappel sur le client dans une configuration de WCF duplex?WCF Duplex: comment gérer l'exception levée en mode duplex Callback

Actuellement, le client ne semble pas déclencher l'événement défaillant (à moins que je ne le surveille pas correctement?) Mais toute suite à l'appel Ping() utilisant le client échoue avec CommunicationException: "L'objet de communication System.ServiceModel .Channels.ServiceChannel, ne peut pas être utilisé pour la communication car il a été abandonné. ".

Comment faire face à cela et recréer le client, etc.? Ma première question est de savoir comment ça se passe. Deuxièmement, comment le gérer?

Mes services et contrats rappel:

[ServiceContract(CallbackContract = typeof(ICallback), SessionMode = SessionMode.Required)] 
public interface IService 
{ 
    [OperationContract] 
    bool Ping(); 
} 

public interface ICallback 
{ 
    [OperationContract(IsOneWay = true)] 
    void Pong(); 
} 

Ma mise en œuvre du serveur:

[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall, ConcurrencyMode = ConcurrencyMode.Single)] 
public class Service : IService 
{ 
    public bool Ping() 
    { 
     var remoteMachine = OperationContext.Current.GetCallbackChannel<ICallback>(); 

     remoteMachine.Pong(); 
    } 
} 

Mon implémentation client:

[CallbackBehavior(UseSynchronizationContext = false, ConcurrencyMode = ConcurrencyMode.Single)] 
public class Client : ICallback 
{ 
    public Client() 
    { 
     var context = new InstanceContext(this); 
     var proxy = new WcfDuplexProxy<IApplicationService>(context); 

     (proxy as ICommunicationObject).Faulted += new EventHandler(proxy_Faulted); 

     //First Ping will call the Pong callback. The exception is thrown 
     proxy.ServiceChannel.Ping(); 
     //Second Ping call fails as the client is in Aborted state 
     try 
     { 
      proxy.ServiceChannel.Ping(); 
     } 
     catch (Exception) 
     { 
      //CommunicationException here 
      throw; 
     } 
    } 
    void Pong() 
    { 
     throw new Exception(); 
    } 

    //These event handlers never get called 
    void proxy_Faulted(object sender, EventArgs e) 
    { 
     Console.WriteLine("client faulted proxy_Faulted"); 
    } 
} 

Répondre

1

Comme il se trouve, vous ne pouvez pas attendre l'événement Faulted être élevé. Donc, la meilleure façon de rétablir la connexion est de le faire lorsque l'appel à la suite de Ping() échoue:

Je vais garder le code simple ici:

public class Client : ICallback 
{ 
    public Client() 
    { 
     var context = new InstanceContext(this); 
     var proxy = new WcfDuplexProxy<IApplicationService>(context); 

     (proxy.ServiceChannel as ICommunicationObject).Faulted +=new EventHandler(ServiceChannel_Faulted); 

     //First Ping will call the Pong callback. The exception is thrown 
     proxy.ServiceChannel.Ping(); 
     //Second Ping call fails as the client is in Aborted state 
     try 
     { 
      proxy.ServiceChannel.Ping(); 
     } 
     catch (Exception) 
     { 
      //Re-establish the connection and try again 
      proxy.Abort(); 
      proxy = new WcfDuplexProxy<IApplicationService>(context); 
      proxy.ServiceChannel.Ping(); 
     } 
    } 
    /* 
    [...The rest of the code is the same...] 
    //*/ 
} 

Il est évident que, dans mon exemple code, l'exception sera renvoyée mais j'espère que c'est utile pour donner aux gens une idée de la façon de rétablir la connexion.

Questions connexes