Sessioni, istanze e concorrenza

Una sessione è una correlazione di tutti i messaggi inviati tra due endpoint. Lacreazione di istanze fa riferimento al controllo della durata di oggetti servizio definiti dall'utente e di oggetti InstanceContext correlati. Laconcorrenza è il termine dato al controllo del numero di thread in esecuzione contemporaneamente in un InstanceContext .

In questo argomento vengono descritte tali impostazioni, come utilizzarle e le varie interazioni tra di esse.

Sessioni

Quando la proprietà ServiceContractAttribute.SessionMode viene impostata da un contratto di servizio su SessionMode.Required, tutte le chiamate, ovvero gli scambi di messaggi sottostanti che supportano le chiamate, devono essere parte della stessa conversazione. Se un contratto consente sessioni ma non ne richiede, i client possono connettersi e possono stabilire o meno una sessione. Se, al termine della sessione, un messaggio viene inviato sullo stesso canale basato sulla sessione, viene generata un'eccezione.

Le principali caratteristiche delle sessioni WCF sono le seguenti:

  • Vengono avviate e terminate esplicitamente dall'applicazione chiamante.

  • I messaggi recapitati durante una sessione vengono elaborati nell'ordine in cui vengono ricevuti.

  • Le sessioni consentono di correlare un gruppo di messaggi in una conversazione. Il significato di tale correlazione è un'astrazione. Un canale basato sulla sessione, ad esempio, è in grado di correlare messaggi basati su una connessione di rete condivisa mentre un altro canale basato sulla sessione è in grado di correlare messaggi basati su un tag condiviso nel corpo del messaggio. Le funzionalità che possono derivare dalla sessione dipendono dalla natura della correlazione.

  • Non esiste alcun archivio dati generale associato a una sessione WCF.

Se si ha familiarità con la classe System.Web.SessionState.HttpSessionState in applicazioni ASP.NET e con la funzionalità fornita, è possibile notare le differenze seguenti tra quel tipo di sessioni e le sessioni WCF:

  • Le sessioni ASP.NET sono sempre avviate dal server.

  • Le sessioni ASP.NET sono implicitamente non ordinate.

  • Le sessioni ASP.NET forniscono un meccanismo di archiviazione dati generale tramite richieste.

Le applicazioni client e le applicazioni di servizio interagiscono con le sessioni in modi diversi. Le applicazioni client avviano sessioni e quindi ricevono ed elaborano i messaggi inviati all'interno della sessione. Le applicazioni di servizio possono utilizzare le sessioni come punto di estensibilità per aggiungere comportamenti. Ciò si ottiene utilizzando direttamente InstanceContext o implementando un provider di contesto dell'istanza personalizzato.

Instancing

Il comportamento delle istanze (impostato tramite la proprietà ServiceBehaviorAttribute.InstanceContextMode ) consente di controllare come viene creato InstanceContext in risposta ai messaggi in ingresso. Per impostazione predefinita, ogni InstanceContext viene associato a uno oggetto servizio definito dall'utente. In questo modo l'impostazione (nel caso predefinito) della proprietà InstanceContextMode consente di controllare anche le istanze di oggetti servizio definiti dall'utente. L'enumerazione InstanceContextMode definisce le modalità di istanza.

Sono disponibili le modalità di istanza seguenti:

  • PerCall: viene creato un nuovo InstanceContext (e di conseguenza l'oggetto servizio) per ogni richiesta client.

  • PerSession: viene creato un nuovo InstanceContext (e di conseguenza l'oggetto servizio) per ogni sessione client nuova e viene mantenuto per la durata di quella sessione (è necessaria un'associazione che supporti sessioni).

  • Single: un unico InstanceContext (e di conseguenza l'oggetto servizio) gestisce tutte le richieste client per la durata dell'applicazione.

Nell'esempio di codice seguente viene illustrato il valore InstanceContextMode predefinito, con PerSession impostato esplicitamente su una classe del servizio.

[ServiceBehavior(InstanceContextMode=InstanceContextMode.PerSession)]
public class CalculatorService : ICalculatorInstance
{
    ...  
}  

Mentre la proprietà ServiceBehaviorAttribute.InstanceContextMode consente di controllare la frequenza di rilascio di InstanceContext , le proprietà OperationBehaviorAttribute.ReleaseInstanceMode e ServiceBehaviorAttribute.ReleaseServiceInstanceOnTransactionComplete consentono di controllare quando l'oggetto servizio viene rilasciato.

Servizi Singleton noti

Una variazione su oggetti servizio di una singola istanza può a volte essere utile. È infatti possibile creare un oggetto servizio e quindi creare l'host del servizio tramite quell'oggetto. A tale scopo, è necessario impostare la proprietà ServiceBehaviorAttribute.InstanceContextMode su Single , in caso contrario verrà generata un'eccezione quando l'host del servizio viene aperto.

Utilizzare il costruttore ServiceHost(Object, Uri[]) per creare tale servizio. Fornisce un'alternativa all'implementazione di un'interfaccia System.ServiceModel.Dispatcher.IInstanceContextInitializer personalizzata quando si desidera fornire un'istanza specifica dell'oggetto utilizzabile da un servizio singleton. Questo overload può risultare utile quando il tipo di implementazione del servizio è di difficile costruzione, ad esempio se non implementa alcun costruttore pubblico privo di parametri.

Si noti che quando un oggetto viene fornito a questo costruttore, alcune funzionalità relative al comportamento di creazione delle istanze di Windows Communication Foundation (WCF) operano in modo diverso. La chiamata, ad esempio, di InstanceContext.ReleaseServiceInstance non ha effetto quando viene fornita l'istanza di un oggetto Singleton. Analogamente, qualsiasi altro meccanismo di rilascio delle istanze viene ignorato. L'host ServiceHost si comporta sempre come se la proprietà OperationBehaviorAttribute.ReleaseInstanceMode fosse impostata su ReleaseInstanceMode.None per tutte le operazioni.

Condivisione di oggetti InstanceContext

È inoltre possibile controllare l'associazione tra canali o chiamate con sessione e oggetti InstanceContext eseguendo quell'associazione.

Concorrenza

La concorrenza è il controllo del numero di thread attivi in un InstanceContext contemporaneamente. Viene controllato tramite ServiceBehaviorAttribute.ConcurrencyMode con l'enumerazione ConcurrencyMode .

Sono disponibili le tre modalità di concorrenza seguenti:

  • Single: ogni contesto dell'istanza può avere al massimo un thread alla volta per l'elaborazione dei messaggi nel contesto dell'istanza. Altri thread che devono utilizzare lo stesso contesto dell'istanza, devono restare bloccati fino alla chiusura del thread originale dal contesto dell'istanza.

  • Multiple: ogni istanza del servizio può avere contemporaneamente più thread per l'elaborazione messaggi. Per essere in grado di usare questa modalità di concorrenza, l'implementazione del servizio deve essere thread-safe.

  • Reentrant: ogni istanza del servizio elabora un messaggio alla volta ma accetta chiamate di operazioni rientranti. Il servizio accetta queste chiamate solo quando è in corso una chiamata in uscita tramite un oggetto client di WCF.

Nota

Può essere difficile comprendere, scrivere correttamente e sviluppare codice che utilizza in modo sicuro più di un thread. Prima di utilizzare valori Multiple o Reentrant , verificare che il servizio sia progettato correttamente per queste modalità. Per ulteriori informazioni, vedere ConcurrencyMode.

L'uso della concorrenza è correlato alla modalità di istanza. Nelle istanze PerCall, la concorrenza non è rilevante, perché ogni messaggio viene elaborato da un nuovo InstanceContext e, di conseguenza, non è mai attivo più di un singolo thread in InstanceContext.

Nell'esempio di codice seguente viene illustrata l'impostazione della proprietà ConcurrencyMode su Multiple.

[ServiceBehavior(ConcurrencyMode=ConcurrencyMode.Multiple, InstanceContextMode = InstanceContextMode.Single)]
public class CalculatorService : ICalculatorConcurrency
{
    ...  
}  

Sessioni che interagiscono con impostazioni InstanceContext

L'interazione di sessioni e di InstanceContext , che dipendono dalla combinazione tra il valore dell'enumerazione SessionMode in un contratto e la proprietà ServiceBehaviorAttribute.InstanceContextMode nell'implementazione del servizio, consente di controllare l'associazione tra canali e oggetti servizio specifici.

Nella tabella seguente viene mostrato il risultato di un canale in ingresso in cui le sessioni sono supportate o non supportate. Tale risultato è in funzione della combinazione dei valori delle proprietà ServiceContractAttribute.SessionMode e ServiceBehaviorAttribute.InstanceContextMode del servizio.

Valore InstanceContextMode Required Allowed NotAllowed
PerCall - Comportamento in caso di canale con sessione: una sessione e un contesto InstanceContext per ogni chiamata.
- Comportamento in caso di canale senza sessione: viene generata un'eccezione.
- Comportamento in caso di canale con sessione: una sessione e un contesto InstanceContext per ogni chiamata.
- Comportamento in caso di canale senza sessione: un contesto InstanceContext per ogni chiamata.
- Comportamento in caso di canale con sessione: viene generata un'eccezione.
- Comportamento in caso di canale senza sessione: un contesto InstanceContext per ogni chiamata.
PerSession - Comportamento in caso di canale con sessione: una sessione e un contesto InstanceContext per ogni canale.
- Comportamento in caso di canale senza sessione: viene generata un'eccezione.
- Comportamento in caso di canale con sessione: una sessione e un contesto InstanceContext per ogni canale.
- Comportamento in caso di canale senza sessione: un contesto InstanceContext per ogni chiamata.
- Comportamento in caso di canale con sessione: viene generata un'eccezione.
- Comportamento in caso di canale senza sessione: un contesto InstanceContext per ogni chiamata.
Singola - Comportamento in caso di canale con sessione: un'unica sessione e un solo InstanceContext per tutte le chiamate.
- Comportamento in caso di canale senza sessione: viene generata un'eccezione.
- Comportamento in caso di canale con sessione: una sessione e un InstanceContext per il singleton creato o per il singleton specificato dall'utente.
- Comportamento in caso di canale senza sessione: un InstanceContext per il singleton creato o per il singleton specificato dall'utente.
- Comportamento in caso di canale con sessione: viene generata un'eccezione.
- Comportamento in caso di canale senza sessione: un contesto InstanceContext per ogni singleton creato o per il singleton specificato dall'utente.

Vedi anche