Desenvolvimento - WCF

WCF – Gerenciamento de Instância

O gerenciamento de instância é uma técnica utilizada pelo WCF que determina como e por quem as requisições dos clientes serão atendidas.

por Marcos Aguiar Jr



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]

    public class Contrato: IContrato

    {

        private int _intContador;

        public int Contador()

        {

            return _intContador++;

        }

    }

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

static void Main(string[] args)

        {

            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 sejacriado. 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ívelaqui.

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

Obrigado.

Marcos Aguiar Jr

Marcos Aguiar Jr - Analista de Sistema com carreira em empresas de tecnologia, atuando em soluções de sistemas e TI para diversos segmentos de negócios, além de definir e planejar metodologias de desenvolvimento de software. É bacharel em Administração com gestão em TI, Pós-Graduação Projeto e Desenvolvimento de Sistemas para WEB e cursando Pós-Graduação em Inteligência de Negócios (BI).