Liberando Streams


Há algum tempo escrevi um artigo sobre transferencia e codificação de dados no WCF. Quando optamos por utilizar o modelo streaming, há um cuidado extra que devemos tomar para efetuar o fechamento dele. Neste cenário sempre há o desafio de saber quando e quem fecha o stream e que foram abordadas no artigo mecionado acima.

Quando alguém envia um stream para o outro lado, este deverá permanecer aberto até que a transferencia seja concluída. Não temos problemas quando o stream é passado diretamente com parametro ou como retorno de uma operação. O problema começa a acontecer quando voce altera a mensagem para que, além do stream, informe dados adicionais, como é mostrado no artigo e ressalto aqui:

[MessageContract]
public class StreamData
{
    [MessageHeader]
    public string NomeDoArquivo;

    [MessageHeader]
    public int Tamanho;

    [MessageBodyMember]
    public Stream Conteudo;
}

Ao retornar esse objeto, o stream relacionado a ele ficará aberto, causando problemas futuros. O WCF possui uma propriedade chamada AutoDisposeParameters, que está acessível através do atributo OperationBehaviorAttribute. Essa propriedade que, por padrão é True, diz ao runtime do WCF para invocar o método Dispose de todos os parametros (input e output) e dos objetos de retorno que implementam a Interface IDisposable e, a partir de agora, conseguimos entender porque quando lidamos com a classe Stream diretamente (ou uma de suas derivadas), o stream é devidamente fechado.

Como já deve suspeitar, o que nos resta fazer é também implementar a Interface IDisposable na classe StreamData e, dentro do método Dispose, invocar o método Dispose dos membros internos, garantindo assim, que o arquivo que está sendo utilizado por essa classe, seja fechado quando o método retornar.

[MessageContract]
public class StreamData : IDisposable
{
    [MessageHeader]
    public string NomeDoArquivo;

    [MessageHeader]
    public int Tamanho;

    [MessageBodyMember]
    public Stream Conteudo;

    public void Dispose()
    {
        if (this.Conteudo != null)
            this.Conteudo.Dispose();
    }
}

Publicidade

Deixe uma resposta

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

Logo do WordPress.com

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

Foto do Facebook

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

Conectando a %s