2012-06-14 11 views
6

In PerSession come si ottiene Dispose() sul servizio da attivare? Nel codice sottostante Dispose() non viene chiamato. Né quando chiamo. Chiudi() né se lascio scadere la sessione.WCF Dispose() Non chiamato con InstanceContectMode = PerSession

Se cambio il servizio in PerCall Dispose() viene chiamato (con ogni chiamata di metodo). Con PerSession sto ottenendo una sessione (testata con serviceStartTime).

Servizio

[ServiceBehavior (InstanceContextMode=InstanceContextMode.PerSession)] 
public class MagicEightBallService : IEightBall, IDisposable 
{ 
    private DateTime serviceStartTime; 
    public void Dispose() 
    { 
     Console.WriteLine("Eightball dispose ... " + OperationContext.Current.SessionId.ToString()); 
    } 
    public MagicEightBallService() 
    { 
     serviceStartTime = DateTime.Now; 
     Console.WriteLine("Eightball awaits your question " + OperationContext.Current.SessionId.ToString() + " " + serviceStartTime.ToLongTimeString()); 
    } 
    public string ObtainAnswerToQuestion(string userQuestion) 
    { 
     return "maybe " + OperationContext.Current.SessionId.ToString() + " " + serviceStartTime.ToLongTimeString(); 
    } 

client

using (EightBallClient ball = new EightBallClient()) 
    {  
     while (true) 
     { 
      Console.Write("Your question: "); 
      string question = Console.ReadLine(); 
      if (string.IsNullOrEmpty(question)) break; 
      try 
      { 
       string answer = ball.ObtainAnswerToQuestion(question); 
       Console.WriteLine("8-ball says: {0}", answer); 
      } 
      catch (Exception Ex) 
      { 
       Console.WriteLine("ball.ObtainAnswerToQuestion exception " + Ex.Message); 
      }    
     } 
     ball.Close(); 
    } 

Service-contratto

[ServiceContract (SessionMode = SessionMode.Required)] 
public interface IEightBall 
{ 
    [OperationContract] 
    string ObtainAnswerToQuestion(string userQuestion); 

    [OperationContract] 
    sDoc GetSdoc(int sID); 

    DateTime CurDateTime(); 
} 

Host metodo

<?xml version="1.0" encoding="utf-8" ?> 
<configuration> 
    <system.serviceModel> 
    <bindings> 
     <wsHttpBinding> 
     <binding name="WSHttpBinding_ISampleService" 
       closeTimeout="00:01:00" openTimeout="00:01:00" 
       receiveTimeout="00:10:00" sendTimeout="00:10:00"> 
      <security mode="Message" /> 
      <reliableSession ordered="true" 
        inactivityTimeout="00:10:00" 
        enabled="true" /> 
     </binding> 
     </wsHttpBinding> 
    </bindings> 
    <services> 
     <service name="MajicEightBallServiceLib.MagicEightBallService" 
       behaviorConfiguration="EightBallServiceMEXBehavior" > 
     <endpoint address="" 
        binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_ISampleService" 
        contract="MajicEightBallServiceLib.IEightBall"> 
     </endpoint> 
     <endpoint address="mex" 
        binding ="mexHttpBinding" 
        contract="IMetadataExchange" /> 
     <host> 
      <baseAddresses> 
      <add baseAddress="http://localhost:8000/MagicEightBallService"/> 
      </baseAddresses> 
     </host>    
     </service> 
    </services> 
    <behaviors> 
     <serviceBehaviors> 
     <behavior name="EightBallServiceMEXBehavior"> 
      <serviceMetadata httpGetEnabled="true"/> 
     </behavior> 
     </serviceBehaviors> 
    </behaviors> 
    </system.serviceModel> 
</configuration> 

namespace MagicEightBallServiceHost 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      Console.WriteLine("**** Console Based WCF Host *****"); 

      using (ServiceHost serviceHost = new ServiceHost(typeof(MagicEightBallService))) 
      { 
       serviceHost.Open(); 
       Console.WriteLine("The service is running"); 
       Console.ReadLine(); 
      } 
     } 
    } 
} 
+0

Il vostro contratto di servizio anche specificato con 'Session = true'? Penso che sia l'unico modo in cui il client sa di dire al server quando ha finito con una sessione. –

+0

@MichaelEdenfield Dove metterei Session = true? Ho provato SessionMode = SessionMode.Required ma questo non ha aiutato. – Paparazzi

+0

'[ServiceContract (Session = True)]' (Non so che questa sia la risposta, so solo che lo faccio sempre con i miei servizi basati sulla sessione.) –

risposta

10

Dispose() sarà licenziato. L'unica domanda è "Quando?".

La risposta a questa domanda dipende dalla configurazione del servizio.

Ci sono diversi scenari possibili:

  1. sessione non è supportata dal legame
  2. sessione normale
  3. sessione affidabile

Dispose() viene licenziato quando la sessione è chiusa per la modalità contesto PerSession. Quindi dobbiamo verificare quanto tempo dura la sessione in diversi scenari.

Per alcune configurazioni (ad esempio predefinita BasicHttpBinding) la sessione non è stata avviata. In caso di configurazione senza sessione, le modalità di contesto PerCall e PerSession non hanno alcuna differenza e il metodo Dispose verrà chiamato molto presto dopo l'esecuzione del metodo principale.

Se Session è abilitato, può essere chiuso esplicitamente dal client o dal timeout. Normalmente è controllato dal cliente. Il client avvia la sessione prima di effettuare la prima chiamata al servizio e la chiude quando l'oggetto client viene chiuso.

metodo
ServiceClient proxy = new ServiceClient(); 
Console.WriteLine(proxy.GetData(123)); 
proxy.Close(); 

proxy.Close() sopra chiude la sessione a server quale a sua volta esegue Dispose().

La gestione delle sessioni è un grande driver di prestazioni perché richiede l'esecuzione di chiamate aggiuntive tra client e server.

Quindi normalmente Dispose verrà chiamato quando il Cliente desidera chiudere la sessione.

Se il client non ha chiuso la sessione per qualsiasi motivo, verrà chiuso dall'host del servizio dopo un determinato periodo di tempo. Tale periodo è controllato dalla proprietà Binding.ReceiveTimeout. Il valore predefinito per quella proprietà è 10 min.

La sessione verrà chiusa e (Dispose() attivata) se nessuno ha inviato la richiesta al server con un ID sessione specifico per 10 minuti. Questo timeout predefinito può essere modificato impostando receiveTimeout su un valore più breve in web.config.

<wsHttpBinding> 
    <binding name="wsHttpEndpointBinding" receiveTimeout="00:00:05"> 
    </binding> 
</wsHttpBinding> 

ReliableSession.InactivityTimeout è inoltre verificata quando la sessione affidabile è abilitato. È anche predefinito per 10 minuti.

Funziona come previsto nei servizi ospitati in hosting e IIS.

tenta di aggiornare il codice client come segue alla prova:

using (EightBallClient ball = new EightBallClient()) 
{  
    ball.ObtainAnswerToQuestion("test"); 
    ball.Close(); 
} 
+0

Si prega di consultare il mio codice. Sto chiamando ball.Close(); e Dispose() non sta sparando. Se lascio scadere la sessione, Dispose() non viene chiamato. Is ball.Close(); non si sta chiudendo il proxy? – Paparazzi

+0

L'ho provato prima di pubblicare una risposta. Tutto ciò che ho detto è vero per il servizio ospitato da IIS usando * .svc. Come ospiti il ​​tuo codice? –

+0

Sto ospitando in una semplice app per console. Posterò l'intero host E grazie – Paparazzi

Problemi correlati