Personalizado Hilo de portarse mal
-
22-12-2019 - |
Pregunta
Dadas las siguientes clases:
type
GEvent = class(TThread)
public
procedure Terminate;
procedure Call(Event : GEvent);
constructor Create;
procedure Execute; Override;
end;
TDirection = (DUp, DRight, DDown, DLeft);
EventTitle = class(GEvent)
private
Index : Integer;
Sprite : CSprite;
Terminate : Boolean;
procedure CreateSprite;
procedure MoveCursor(Direction : TDirection);
procedure RefreshCursor;
constructor Create;
destructor Destroy;
public
procedure Execute;
end;
implementation
{ GEvent }
procedure GEvent.Call(Event: GEvent);
begin
Suspend;
// inherited Terminate;
Self := GEvent(Event.ClassType.Create);
end;
constructor GEvent.Create;
begin
inherited Create(True);
end;
destructor GEvent.Destroy;
begin
Terminate;
inherited;
end;
procedure GEvent.Execute;
begin
// inherited;
end;
procedure GEvent.Terminate;
begin
Suspend;
inherited;
end;
{ EventTitle }
constructor EventTitle.Create;
begin
inherited;
Resume;
end;
procedure EventTitle.CreateSprite;
begin
Showmessage('anything');
end;
destructor EventTitle.Destroy;
begin
inherited;
end;
procedure EventTitle.Execute;
begin
inherited;
Synchronize(CreateSprite);
Index := 0; {
while not Terminated do
begin
if GISystem.System.Input.Trigger(KUp) then
MoveCursor(DUp);
if GISystem.System.Input.Trigger(KDown) then
MoveCursor(DDown);
end; }
end;
Cuando la principal forma de llamadas InstanceVar := EventTitle.Create
automáticamente el Hilo debe alcanzar el método CreateSprite
, lo que, extrañamente, no está sucediendo.Yo no podía entender por qué el método no está siendo ejecutado.El formulario principal de la aplicación sigue funcionando bien, pero parece que el EventTitle.Execute
se detiene abruptamente o incluso no se inician.Es maight ser misimplementation así.Es mi primer MultiThreading juicio, entonces lo siento por cualquier inconsistencia.¿Puede alguien ver lo que hice mal?
Solución
Hay algunos problemas obvios aquí.No estoy seguro de que la fijación de ellos va a resolver tu problema, pero yo no estaría sorprendido:
- Su
Execute
el método debe ser declarada conoverride
para que se ejecute.Esto explica el comportamiento que se informe. - Su destructor debe ser declarada con
override
para que se ejecute.Tenga en cuenta que implementarGEvent.Destroy
pero elGEvent
la clase no declarar un destructor.Así el código de la pregunta no compila. - No llame
Terminate
en el destructor de la clase thread.El destructor de la clase baseTThread.Destroy
termina y se espera para el hilo.Quitar la llamada aTerminate
enGEvent.Destroy
. - Su
Terminate
método ocultaTThread.Terminate
.Que es muy mala práctica.Estoy seguro de que el compilador avisa de esto.Usted debe prestar atención a las advertencias.Tal y como está el hilo del destructor suspende el hilo y, a continuación, espera a que termine.Es mejor que la esperanza de que el hilo ya ha terminado de ejecutar en el momento de destruirlo. - No tiene sentido crear un hilo suspendido solamente a reanudar de inmediato de ella.Aunque no hay ningún problema real, que serán causados por el que.
- El código de
GEvent.Call
es absolutamente falso.Nunca ceder aSelf
.Debe quitar ese código. - Todas tus llamadas a
Suspend
están equivocados.Usted no debe llamar aSuspend
.Tiene resultados impredecibles.Eliminar las llamadas aSuspend
.
Un error repetidos que han hecho de la omisión de override
.La palabra clave se utiliza para reemplazar un método virtual.En el caso de la Execute
el método, y el destructor, estos son los métodos virtuales llamado por una clase base.Como tal, si no invalidar el método virtual, simplemente introduciendo un nuevo método en la clase derivada.Y cuando la clase base se llama al método virtual, el nuevo método no se ejecutará.
Le sugiero que empiece con este código:
type
EventTitle = class(TThread)
private
procedure DoSomething;
public
constructor Create;
procedure Execute; override;
end;
implementation
constructor EventTitle.Create;
begin
inherited Create(False);
end;
procedure EventTitle.DoSomething;
begin
ShowMessage('anything');
end;
procedure EventTitle.Execute;
begin
Synchronize(DoSomething);
end;
Me he despojado de casi todo el código, pero casi todo estaba mal.