Ir para o conteúdo
Alfonso CV

Bloquear programa.

Mensagens Recomendadas

Alfonso CV

Olá pessoal.

Uso Lazarus 1.8.4

Tenho uma aplicação que lê dados remotos, imagem e documentos gravados numa base de dados, o assunto é que quando são grandes e demoram um pouco a gente acha que o sistema está bloqueado, já coloquei barra de progresso e GIF dinâmico mas quando começa a fazer download estes controles param e o programa não responde. Também, se são varias imagens pequenas de 200 KB por exemplo depois de iniciar até não concluir o processo de download a aplicação não responde.

Já usei DELAY e SLEEP para refrescar o Form entre download e nada, a aplicação entra num estado de Stand-by e até não terminar não responde.

Alguma dica???

Cumprimentos,

 

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
nunopicado

O problema é que estás a fazer o download na thread principal, onde também corre o UI do programa. 

Em termos simplistas, numa mesma thread, o CPU do computador pode correr apenas uma instrução de cada vez... 

Tu estás a tentar fazer as instruções do download e as instruções da actualização do UI em simultâneo, pelo que uma delas acaba por ficar para trás. 

Por causa disto, quando há processos demorados, estes devem ser corridos numa segunda thread, deixando a principal encarregue de actualizar o UI. 

Assim já funcionará correctamente. 


"A humanidade está a perder os seus génios... Aristóteles morreu, Newton já lá está, Einstein finou-se, e eu hoje não me estou a sentir bem!"

> Não esclareço dúvidas por PM: Indica a tua dúvida no quadro correcto do forum.

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
Alfonso CV

Olá Nuno.

Consegui resolver o problema colocando no código o seguinte:

Application.ProcessMessages;

Cumprimentos.

 

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
nunopicado

O Application.ProcessMessages é largamente usado para 'desenrascar' esse problema, mas o seu uso não é sem custos...

Este método serve para 'avisar' o programa para processar as mensagens (duh! :D) que estão na queue do Windows, independentemente de quais são e do risco associado à execução de mensagens fora de ordem.

Antes de mais, uma explicação simplista do que são 'mensagens': O GUI do Windows funciona porque os seus elementos enviam mensagens uns aos outros com indicação do que querem fazer. Por exemplo, quando clicas num botão, é enviada uma mensagem para o componente encarregue de alterar o aspecto visual do botão (que o faz parecer 'pressionado' visualmente) que por sua vez manda uma mensagem à form para se redesenhar para que o novo aspecto seja mostrado, há uma mensagem a dar iniciação do trabalho do botão, etc.

Ao fazer ProcessMessages, estás a forçar a main thread do programa a executar tudo o que estiver na fila, e isto tem, de entre outras, as seguintes consequências:

  • Estás a parar temporariamente a execução da tarefa principal, obrigando-a a demorar mais tempo
  • Estás a mandar executar mensagens a meio da tarefa, sem saber quais as mensagens que lá estão nem os problemas que a sua execução forçada pode causar.

No caso, a tua ideia faz com que ele pare a leitura dos dados, actualize o UI ao processar as mensagens de actualização que estão pendentes, e volta a ler, e voltar a parar, e por aí fora até completar a leitura.
Como à primeira vista, isto funciona, muita gente o faz.

O que muitos desconhecem é que, ao fazer isto, podem estar com uma simples linha a introduzir bugs no programa, bugs esses que são de detecção extremamente difícil pois existem pela execução de mensagens fora da ordem correcta. O caso é tal que podes correr um programa e dar tudo bem, voltas a correr sem alterar nada e os bugs manifestam-se, voltas a correr e está tudo bem, voltas a correr e aparecem bugs completamente diferentes dos primeiros. Ou seja, o pesadelo de qualquer programador.

Por outro lado, dependendo das mensagens pendentes, o resultado pode nem ser o esperado, e não resolve sequer o problema inicial. Podes agora 'resolver' assim, e noutro programa em que te depares com um problema semelhante, resolves usar o mesmo, mas nesse outro programa não funcionar, por um qualquer motivo. Isto retira-te a previsibilidade das soluções, o que te obrigará a perder tempo à procura da solução de cada vez que te surgir o problema.
E se o utilizador for dado a clicar à toa enquanto espera, como há tantos por aí, o resultado é muitas vezes o crash do programa, porque independentemente de lhe mandarmos processar as mensagens, a thread continua a ser só uma, e nem sempre com capacidade de fazer tudo o que lhe pedem.

Nota: Não estou com isto a dizer que nunca se deve usar o ProcessMessages, ou que no teu caso não resolva o problema sem introduzir outros. Tudo depende do código circundante ao ProcessMessages. E mesmo quando os bugs aparecem, podem ser coisas tão banais quanto uma barra de progresso que anda para a frente e depois volta atrás, para depois voltar pra frente, não afectando nada de especial senão o aspecto visual.

Mas há casos bem mais graves, o que me leva a recomendar que quem não saiba exactamente o que está a acontecer, ignore o 'remendo' que é o ProcessMessages, em favor de uma solução mais previsível, como o uso de multi-threading.

Nota 2: Multi-threading não é, no entanto, um mar de rosas. É preciso perder algum tempo para sequer começar a ter ideia do ninho de ratos que aquilo é. No entanto, a partir do momento que saibas usar e implementares com as devidas protecções, é mais previsível e consistente do que correr mensagens desconhecidas a meio de uma tarefa.

Editado por nunopicado
  • Voto 2

"A humanidade está a perder os seus génios... Aristóteles morreu, Newton já lá está, Einstein finou-se, e eu hoje não me estou a sentir bem!"

> Não esclareço dúvidas por PM: Indica a tua dúvida no quadro correcto do forum.

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
Alfonso CV

Olá Nuno.

Como já tenha dito, de momento resolvi mas acho que vamos a ter em conta teu comentário pois se facilita a execução do programa e contribui a ser um bocadinho mais rápido alem das possíveis consequências quando se produz alguns erro vale a pesa dar uma olhada neste tema. 

Cumprimentos.

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites

Crie uma conta ou ligue-se para comentar

Só membros podem comentar

Criar nova conta

Registe para ter uma conta na nossa comunidade. É fácil!

Registar nova conta

Entra

Já tem conta? Inicie sessão aqui.

Entrar Agora

×

Aviso Sobre Cookies

Ao usar este site você aceita os nossos Termos de Uso e Política de Privacidade. Este site usa cookies para disponibilizar funcionalidades personalizadas. Para mais informações visite esta página.