PDA

Ver la Versión Completa : GetTickCount vs. TTimer


Wonni
17-07-2006, 13:41:17
Hola :)

Tengo el libro de los tomos de Delphi: "Nucleo del Api Win32" y en el capitulo 15 ( Funciones de temporización ) trae un ejemplo de como emular un temporizador. El ejemplo muestra un label parpadeando. El caso es que yo pense que tratando con el Api ( tal y como dice el libro ) se consigue una mejor ejecucion del programa, consumir menos recursos. Pues resulta que construyo el programita con dos opciones:

1ª - Mostrar el label parpadeando con un TTimer y
2ª - Mostrar el label parpadeando con el codigo que trae el libro utilizando GetTickCount.

Cuando ejecuto el programa con el TTimer, voy al monitor del sistema y el uso de CPU no sube nunca del 1 %

Cuando ejecuto el programa con GetTickCount, el uso de CPU no se mueve del 100 % !!!! :eek:

¿como es posible? se supone que deberia ser mas liviano.

Este es el codigo completo:

unit Principal;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ExtCtrls;
type
TFormPrincipal = class(TForm)
BotonIniciarConGet: TButton;
LabelDelphi: TLabel;
BotonDetenerGet: TButton;
BotonIniciarConTTimer: TButton;
BotonDetenerTTimer: TButton;
TimerParpadeo: TTimer;
procedure BotonIniciarConGetClick(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure BotonDetenerGetClick(Sender: TObject);
procedure BotonIniciarConTTimerClick(Sender: TObject);
procedure BotonDetenerTTimerClick(Sender: TObject);
procedure TimerParpadeoTimer(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
FormPrincipal: TFormPrincipal;
Running: Boolean; // variable de control del bucle

implementation
{$R *.dfm}
Procedure Timerando;
Begin
End;
Procedure FlashLoop;
Var
StartTick: DWORD; // Hora de inicio
Begin
//Obtener la hora actual
StartTick := GetTickCount;
//Si el bucle continua...
While Running Do
Begin
//...si ha trasncurrido un segundo
If (GetTickCount - StartTick) > 1000 Then
Begin
//...actualizar etiqueta
FormPrincipal.LabelDelphi.Visible := not FormPrincipal.LabelDelphi.Visible;
//Reinicializar hora de inicio para siguiente iteracion
StartTick := GetTickCount;
End;
// Necesario para que el bucle no "bloquee" la maquina
Application.ProcessMessages;
End;
End;
procedure TFormPrincipal.BotonIniciarConGetClick(Sender: TObject);
begin
//Inicializar variable de control...
Running := TRUE;
//... y lanzar el bucle
FlashLoop;
end;
procedure TFormPrincipal.FormClose(Sender: TObject; var Action: TCloseAction);
begin
Running := FALSE;
TimerParpadeo.Enabled := FALSE;
end;
procedure TFormPrincipal.BotonDetenerGetClick(Sender: TObject);
begin
Running := FALSE;
end;
procedure TFormPrincipal.BotonIniciarConTTimerClick(Sender: TObject);
begin
TimerParpadeo.Enabled := TRUE;
end;
procedure TFormPrincipal.BotonDetenerTTimerClick(Sender: TObject);
begin
TimerParpadeo.Enabled := FALSE;
end;
procedure TFormPrincipal.TimerParpadeoTimer(Sender: TObject);
begin
FormPrincipal.LabelDelphi.Visible := not FormPrincipal.LabelDelphi.Visible;
end;
end.


Saludos !!

seoane
17-07-2006, 13:54:37
El problema no es con la función GetTickCount, que tiene sus manías pero esta no es una de ellas. Lo que pasa es que la utilizas dentro de un bucle, si no haces algún tipo de espera dentro del bucle este termina usando la CPU al 100%. Una solución sencilla es hacer una pequeña espera dentro del bucle.


StartTick := GetTickCount;
//Si el bucle continua...
While Running Do
Begin
//...si ha trasncurrido un segundo
If (GetTickCount - StartTick) > 1000 Then
Begin
//...actualizar etiqueta
FormPrincipal.LabelDelphi.Visible := not FormPrincipal.LabelDelphi.Visible;
//Reinicializar hora de inicio para siguiente iteracion
StartTick := GetTickCount;
End;
// Necesario para que el bucle no "bloquee" la maquina
Application.ProcessMessages;
Sleep(100); // Aqui le damos tiempo a la CPU para respirar
End;

Wonni
17-07-2006, 14:03:21
Gracias seoane, funciona muy bien :)

Ahora en el monitor de sistema consume exactamente igual GetTickCount que TTimer. No se mueve del 1% ( a veces 0 en ambos metodos ).

Entonces, supongo que da igual uno q otro. ¿no?

Saludos !!

seoane
17-07-2006, 14:16:33
Entonces, supongo que da igual uno q otro. ¿no?


Yo creo que se utilizan para hacer cosas diferentes. Mientras que GetTickcount es muy útil para controlar el tiempo dentro dentro de una función, por ejemplo para implementar un Timeout, si lo que queremos es ejecutar un evento a intervalos regulares es mucho mejor usar un TTimer, que a fin de cuentas solo encapsula las APIs SetTimer y KillTimer.

Wonni
17-07-2006, 14:32:57
ok, ya me ha quedado claro.

Gracias otra vez seoane :)

Saludos !!