in C#

C# e PowerShell – objetos IDisposable

Alguns meses atrás automatizei um processo de deploy utilizando PowerShell, basicamente ele tirava servidor por servidor do NLB, sincronizava os arquivos e realizava alguns GET’s em um lista de urls. Para realizar a requisição web, eu optei por criar um objeto do tipo System.Net.WebRequest, e realizar a requisição. Porém notei que o processo travava, demorava muito e até retornava timeout, quanto tinha mais de uma url para testar.

Abaixo segue um exemplo do código que apresentava timeout:

Sem Dispose

$urls=("http://www.google.com.br","http://www.google.com.br","http://www.google.com.br","http://www.google.com.br","http://www.google.com.br","http://www.google.com.br","http://www.google.com.br","http://www.google.com.br","http://www.google.com.br","http://www.google.com.br")

foreach($item in $urls){
    $request = [System.Net.WebRequest]::Create($item)
    $response=$request.GetResponse()
    $response.StatusCode
}

Estava estudando e tentando resolver este problema quando percebi um erro básico neste script (que ainda cometemos em muitos códigos), estamos utilizando um código que trabalha com código não gerenciado (podemos resumir em códigos que acessam APIs, Network, Window, IO, etc). Para este tipo de objeto, é necessário a implementação e o uso do Dispose, pois ele não consegue saber o momento desalocar os recursos que estavam sendo utilizados. No caso do webrequest ele estava travando com um numero máximo de requisições que o cliente poderia realizar com aquele servidor em específico (além de consumir memória).

Pensando nisto mudei o código e implementei da seguinte maneira:

Com Dispose

$urls=("http://www.google.com.br","http://www.google.com.br","http://www.google.com.br","http://www.google.com.br","http://www.google.com.br","http://www.google.com.br","http://www.google.com.br","http://www.google.com.br","http://www.google.com.br","http://www.google.com.br")

foreach($item in $urls){
    Try{
        $request = [System.Net.WebRequest]::Create($item)
        
        $response=$request.GetResponse()
        $response.StatusCode
    }
    Catch{
        Write-Host $_.Exception.Message
    }
    Finally
    {
        If($response){
            $response.Close()
            $response.Dispose()
        }
    }
}

Com isto ele executa todas as requisições e fecha a conexão com o web server, mesmo que ocorra algum erro.

Abaixo segue um vídeo com o exemplo dos dois códigos, a diferença é grande 🙂

A dica que queria passar é: independente de estarmos trabalhando com PowerShell é muito importante se preocupar com performance, uso de recursos e Dispose.

Estou a disposição para dúvidas, criticas e sugestões.

abs

Rodolfo

  • Robson Alves

    Legal!!