Momento POG: O famoso GOTO
Muito “discriminado” pelos programadores mais experientes, e os mais novos raramente usam, a instrução GOTO virou sinônimo de Gambiarra.
Existente desde os primórdios da programação, serve basicamente para saltarmos incondicionalmente para um ponto do programa, geralmente determinado por um label (não, não é o componente de interfaces gráficas que você está pensando não).
Substituído por IF’s e outras estruturas de controle de fluxo, ninguém lembra que ele existe.
Mas até mesmo em C# ele me salvou de algumas :-)
Tive que terminar um Console Application cuja função é verificar uma caixa de e-mail a cada tantos segundos, e ao pressionar a tecla “Q” a aplicação se encerrava.
Verificar a caixa a cada tantos segundos… imediatamente me veio a idéia de instanciar um Timer, coisa que eu fiz: Configurei no método Main() da aplicação o timer e tal.
Só que aí veio um pequeno problema: o método Main() era executado e a aplicação saia do ar.
Me vieram algumas idéias:
1. Fazer a aplicação esperar uma tecla: Coloquei um método ReadKey(), pois assim o fluxo do método Main() ficaria esperando até que o usuário pressionasse uma tecla, porém o Timer ficaria executando em uma thread a parte (isso é automático), mas teria o problema do usuário ir lá, apertar QUALQUER tecla e a aplicação sai do ar.
1: static void Main(string[] args)
2: {
3: /*Declaração e configuração do timer...*/
4:
5: Console.Write("Pressione qualquer tecla para sair...");
6: Console.ReadKey();
7:
8: }
2. Fazer um looping até que uma determinada tecla seja pressionada: Como eu disse acima, somente ao pressionar a tecla “Q” é que o programa deveria sair do ar. Veja como ficou o código:
1: static void Main(string[] args)
2: {
3: /*Declaração e configuração do timer...*/
4:
5: ConsoleKeyInfo k = new ConsoleKeyInfo();
6: Console.Write("Pressione 'Q' para sair...");
7: while (!k.KeyChar.ToString().ToUpper().Equals("Q"))
8: {
9: k = Console.ReadKey();
10: }
11: }
O timer continuaria executando em uma thread à parte, porém temos um probleminha: O looping faz o programa consumir praticamente toda a CPU para si! E como o servidor onde vai rodar esse bicho BOMBA, isso é inadmissível.
3. A Solução definitiva: Como “prender” a saída da aplicação a uma determinada tecla, modificando o fluxo do método Main() sem usar um looping? Foi com essa idéia que tive o insight de usar o famigerado GOTO com o auxílio de um if:
1: static void Main(string[] args)
2: {
3: /*Declaração e configuração do timer...*/
4:
5: ConsoleKeyInfo k = new ConsoleKeyInfo();
6: Console.Write("Pressione 'Q' para sair...");
7: fluxo:
8: k = Console.ReadKey();
9: if (!k.KeyChar.ToString().ToUpper().Equals("Q"))
10: {
11: goto fluxo;
12: }
13: }
Como você pode ver, declarei o label fluxo antes da instrução que faz a aplicação guardar uma tecla, e após uma tecla ser pressionada é feita uma verificação: Se for diferente de “Q”, o programa volta para a instrução de aguardar uma tecla.
Com isso, o programa não consome muita CPU e o meu Timer ficou executando em outra thread, e fazendo o que tem que fazer!
PS: Já prevendo, eu sei que para este caso a melhor alternativa seria fazer um Windows Service, porém eu ainda não sei como construir um (e nem tive tempo de dar uma googlada sobre o assunto :-( ). Como o programa em si está em uma biblioteca de classes, a implementação é muito simples, pois é só instanciar a classe e chamar os métodos dentro do evento OnElapsed de um Timer (igual foi feito no Console Application).
Um abraço!
2 comentários:
Quem nunca fez um POG coloque a mão aqui...
De qq. forma dou graças a Deus não trabalhar mais com backend e ter que apelar para coisas desse tipo.
*não que, com frontend, não apelemos com coisas diferentes - e talvez até piores!
[]s!
@Chris
Verdade... no front end ainda temos que encarar os "resquícios" da Guerra dos Browsers (principalmente quem faz app web).
Mas graças a Deus que eu me resignei e no lugar do Console Application, fiz uma aplicação Windows Form que fica no SysTray, assim "matei" essa POG e a aplicação ficou mais elegante hehe.
[]'s!
Postar um comentário