Início > WCF > Gerenciamento de Instância no WCF

Gerenciamento de Instância no WCF

Olá a todos.

Esse artigo irá falar sobre gerenciamento de instância no WCF e para que você possa entender esse artigo é necessário ter um conhecimento básico em WCF.

Existem três formas de realizar requisições através de um serviço WCF. Essas formas são conhecidas como gerenciamento de instancia e ajudam a melhorar o desempenho e a segurança do WCF.

Antes de explicar cada gerenciamento de instância, vou mostrar abaixo o código fonte que vamos utilizar para os exemplos. Lembre-se é recomendado ter conhecimento em WCF.

Vamos utilizar um projeto Console. Primeiro vamos criar a seguinte Interface:

[ServiceContract]
public interface IContrato
{
    [OperationContract]
    int Contador();
}

Em seguida uma classe que é herdada dessa Interface com a implementação do método Contador:

[ServiceBehavior(InstanceContextMode=InstanceContextMode.PerSession)]
public class Contrato: IContrato
{
    private int _intContador;

    public int Contador()
    {
        return _intContador++;
    }
}

Em Program.cs no método Main digite o seguinte código:

using (ServiceHost host = new ServiceHost(typeof(Contrato), new Uri[] { new Uri("net.tcp://localhost:9393") }))
{
    host.Description.Behaviors.Add(new ServiceMetadataBehavior());
    host.AddServiceEndpoint(typeof(IContrato), new NetTcpBinding(), "srv");
    host.AddServiceEndpoint(typeof(IMetadataExchange), MetadataExchangeBindings.CreateMexTcpBinding(), "mex");

    host.Open();

    Console.WriteLine("[ O Serviço está rodando ]");

    Console.ReadLine();

    using (ChannelFactory<IContrato> f = new ChannelFactory<IContrato>(new NetTcpBinding(),               "net.tcp://localhost:9393/srv"))
{
    var channel = f.CreateChannel();
    for (int intContador = 0; intContador < 5; intContador++)
    {
        Console.WriteLine(channel.Contador().ToString());
    }

}

using (ChannelFactory<IContrato> f = new ChannelFactory<IContrato>(new NetTcpBinding(), "net.tcp://localhost:9393/srv"))
{
    var channel = f.CreateChannel();
    for (int intContador = 0; intContador < 5; intContador++)
    {
        Console.WriteLine(channel.Contador().ToString());
    }
}

Console.ReadLine();

Para esse exemplo estou criando o host e a chamada ao serviço em uma única aplicação, isso não é correto em um projeto, mas para um exemplo será útil. Depois de criar o host, crio dois proxy (instância do serviço) que  realizaram cinco requisições cada um.

Bem com esse código pronto vamos às explicações.

PerSession

Esse é a instância padrão do WCF. Quando a aplicação cliente cria uma proxy, esse proxy ira realizar todas as conexões com o serviço que o cliente chamar, até que o método Close (ou Dispose) seja chamado e o proxy seja encerrado. Enquanto o proxy não for fechado todas as alterações feita nos membros internos do serviço (como em uma propriedade global como no nosso exemplo em _intContador) será armazenada. Caso a aplicação cliente crie dois proxy , cada proxy irá controlar sua memoria, não interferindo um proxy no outro.

Como já escrevi, o PerSession é a instancia default do WCF, nesse caso não precisamos informá-la quando desejamos utilizar, mas em nosso exemplo vamos especificar. Vamos dizer ao WCF para trabalhar com PerSession na classe do serviço (no nosso exemplo na classe Contrato), como exemplo abaixo:

[ServiceBehavior(InstanceContextMode=InstanceContextMode.PerSession)]

Ao executar nosso exemplo temos o seguinte resultado:

A propriedade _intContador é incrementada sempre que o proxy é chamado, porém quando o proxy é finalizado e uma novo proxy é criado, o _intContador começa do zero (propriedade int por padrão começa com valor zero), pois a instância anterior foi perdida.

PerCall

Diferente do PerSession o PerCall cria uma nova requisição do proxy, ou seja, quando a operação é finalizada o proxy é removido da memoria.  Para utilizarmos o PerCall precisamos alterar na classe Contador o InstanceContextMode conforme exemplo abaixo:

[ServiceBehavior(InstanceContextMode=InstanceContextMode.PerCall)]

Ao executar nosso exemplo após a alteração, temos o seguinte resultado:

O resultado sempre será zero porque, apesar de realizar N requisições ao serviço a propriedade _intContador não é incrementada.

Single

Single tem uma maneira diferente de se comportar. Existir apenas uma única instancia do proxy que ira servir para todas as requisições, mesmo que o Close ou Dispose sejam chamados ou que um novo objeto proxy seja criado. Para utilizarmos o Single precisamos alterar na classe Contador o InstanceContextMode conforme exemplo abaixo.

[ServiceBehavior(InstanceContextMode=InstanceContextMode.Single)]

Mesmo descartando o primeiro proxy, quando começamos a utilizar o segundo proxy o _intContador continua sendo incrementando com o valor que foi finalizado pelo primeiro proxy, conforme podemos ver na imagem abaixo:

Você deve-se perguntar qual é a melhor? Isso depende, ninguém melhor do que você para decidir qual tipo de gerenciamento de instância é a melhor para a sua solução. Só devemos tomar cuidado porque a instância está ligada ao binding, ou seja, nem todos os binding (como BasicHttpBinding) suportar esse exemplo que implementamos.

O código fonte desse exemplo está disponível aqui.

Espero que tenham gostado e até a próxima.

Obrigado.

Anúncios
  1. Nenhum comentário ainda.
  1. No trackbacks yet.

Deixe um comentário

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s

%d blogueiros gostam disto: