Tópico personalizado com comportamento inadequado
-
22-12-2019 - |
Pergunta
Dadas as seguintes classes:
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;
Quando o formulário principal chama InstanceVar := EventTitle.Create
automaticamente o Thread deve chegar ao método CreateSprite
, o que estranhamente não está acontecendo.Não consegui entender por que o método não está sendo executado.A forma principal do aplicativo ainda funciona bem, mas parece que o EventTitle.Execute
pára abruptamente ou até mesmo não inicia.Também pode ser uma má implementação.É meu primeiro teste MultiThreading, então desculpe qualquer inconsistência.Alguém pode ver o que eu fiz de errado?
Solução
Existem alguns problemas óbvios aqui.Não tenho certeza se corrigi-los resolverá seu problema, mas não ficaria surpreso:
- Seu
Execute
o método deve ser declarado comoverride
para que ele funcione.Isso explica o comportamento que você denuncia. - Seu destruidor deve ser declarado com
override
para que ele funcione.Observe que você implementaGEvent.Destroy
mas oGEvent
classe não declara um destruidor.Portanto o código da pergunta não compila. - Não ligue
Terminate
no destruidor de uma classe de thread.O destruidor da classe baseTThread.Destroy
termina e aguarda o thread.Remova a chamada paraTerminate
emGEvent.Destroy
. - Seu
Terminate
método escondeTThread.Terminate
.Essa é uma prática muito ruim.Tenho certeza que o compilador avisa sobre isso.Você deve prestar atenção aos avisos.Da forma como está, o destruidor do seu thread suspende o thread e espera que ele termine.É melhor você torcer para que o thread já tenha terminado de ser executado no momento em que você o destrói. - Não faz sentido criar um thread suspenso apenas para retomá-lo imediatamente.Embora não haja nenhum problema real que será causado por isso.
- O código em
GEvent.Call
é totalmente falso.Nunca atribua aSelf
.Você deve remover esse código. - Todas as suas chamadas para
Suspend
está errado.Você não deve ligarSuspend
.Tem resultados imprevisíveis.Remova as chamadas paraSuspend
.
Um erro repetido que você cometeu foi a omissão de override
.Essa palavra-chave é usada para substituir um método virtual.No caso do Execute
método e o destruidor, são métodos virtuais chamados por uma classe base.Dessa forma, se você não substituir o método virtual, estará simplesmente introduzindo um novo método na classe derivada.E quando a classe base chama o método virtual, seu novo método não será executado.
Sugiro que você comece com 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;
Retirei quase todo o seu código, mas quase tudo estava errado.