Response.Flush()

Nestes últimos 2 dias eu perdi um tempo impressionante com algo que em tese deveria ter sido extremamente simples de fazer, tipo 5 minutos…  A idéia era fazer um página que iria rodar uma operação longa ir mostrando o andamento da operação, algo como “Passo 1 executado”, “Passo 2 executado” e assim por diante…

Como a regra de negócio estava pronta, achei que fosse trivial ir gerando as tags <p> e ir mostrando o andamento com flushs… Não poderia estar mais errado! Inicialmente tentei usar o HtmlWriter do Render pra ir fazendo os Writes intercalados com os Response.Flush() (fiz um teste com Sleep() pra simular o processamento). Mas não funcionou, ele mostrava a página só no final, com todos os passos de uma vez.

Aí comecei o processo conhecido de buscar no google alguma dica ou esperiência pra entender o que estava errado. Nem precisa falar que o help da MSDN era inútil, aliás copiei e colei o exemplo deles e mesmo comportamento. Comecei a ver que este é um problema para muitas pessoas, aparentemente em algumas situações o Response.Flush() simplesmente não funciona e um mesmo código que funciona para um (como o exemplo da MSDN) não funciona pra outros.

Claro que deve ter algo na página ou no ambiente que faz com que este probelma apareça. Gastei umas boas 4 horas tentando eliminar o que era, utilizando as dicas que achei de pessoas no google para tentar mapear o que era. Mas a questão é que parecia que vários tipos de problemas acabavam se sobrepondo, o principal sendo um próprio entendimento do que o Flush() deveria fazer. Na minha visão (e na visão de várias pessoas que eu vi), ele deveria simplesmente fazer com que o conteúdo gerado até ali fosse para o browser. Mas até sobre isto haviam dúvidas. E aí vinham várias receitas, pra ligar ou desligar buffer, pra fazer com código <% %> intercalado na página ou em determinado evendo em code-behind e até para fazer várias vezes em sequência o comando Flush() para que ele funcionasse! Nenhuma alternativa funcionou pra mim, fui dormir para tentar de novo no dia seguinte.

No dia seguinte, mais 2h. O tempo gasto nisto já estava absurdo e poderia até ter feito com javascript simples, mas vocês sabem, vira questão de honra!  Continuando as busca no google, achei um comentário dizendo que uma instrução específica, faria toda a diferença: Response.BufferOutput = false. E neste cenário, realmente funcionou, mas somente no código aspx direto! Já que neste caso estava funcionando, comecei a tentar isolar o que realmente causava o probelma. Mas não tive sucesso, qualquer pequena alteração fazia com que o código deixasse de funcionar. Desisti, o código final ficou desta forma:

—————————————————————————————————————–

<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN”  “http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”><html  >
<head><title>Correçao de Pesquisa</title></head>
<body style=”font-family: Calibri, Tahoma, Arial”>
<p>Correção em Progresso. Aguarde por favor….</p>
<%  Response.Buffer = false;
Response.BufferOutput = false;
for (var i = 0; i < 10; i++) {
%><span>teste</span><br /><%
Response.Flush();
System.Threading.Thread.Sleep(1000);
} %>
</body>
</html>
—————————————————————————————————————–
Impressionante que este código não funciona se for colocado no evento Load ou Render da página. De fato deve ter alguma coisa no ambiente que impede isto, mas tive que dar um basta no tempo perdido para este problema. Ah, mais um ponto interessante, a tag SPAN funciona melhor do que a tag P – que mesmo com o código funcionando dá uma impressão de agrupamento ao ser mostrado no browser.

Enfim, é impressionante como perdemos tempo com coisas triviais. Esta do Response.Flush é mais um exemplo. Fazer software é muito bom, mas este tipo de coisa não é muito!

, , , ,

  1. #1 por Diogo Menezes em 28/05/2010 - 12:12 pm

    Fala Alexandre, estou passando pelo mesmo problema que você.

    É realmente ridículo isso não funcionar.

    O meu cenário é implementar uma progressbar em asp net…

    Tenho 2 classes com o padrão observer funcionando e avisando as modificações, mas infelizmente não consigo atualizar a página como flush.

    Tentei com update panel + label e também não funciona 😦

    Uma coisa que eu reparei é que se você ser um refresh (f5) em uma página com o flush no CS, ela incrivelmente funciona !!!!

    • #2 por Alexandre Valente em 30/05/2010 - 6:43 am

      Complicado mesmo…. O melhor aí acho que é montar algo que possa ser chamado pelo client side e fazer tudo em jscript.

  2. #3 por Flavio Chapela em 23/01/2011 - 6:36 pm

    Realmente essa operação é um terror.
    Recentemente passei por um problema parecido, e descobri que parte dele provem do IIS. Ao dar o primeiro flush ele apaga os Headers da pagina, ou seja, na primeira descarga o navegador deixa de saber que tipo de documento esta sendo retornado, entao ele espera a conclusao do processamento para poder dar o retorno correto.
    Experimente dar um flsh inicial, em sequencia adicionar via codigo os cabeçalhos da pagina, Ex:

    Response.ClearHeaders();
    Response.Clear();
    Response.Buffer = true;
    Response.ContentType = “Tipo de retorno”;
    Response.AddHeader(“cabeçalhos adicionais”);

    Att Flavio

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: