Personnalisé Fil défaillante
-
22-12-2019 - |
Question
Étant donné les classes suivantes:
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;
Lorsque la principale forme d'appels InstanceVar := EventTitle.Create
automatiquement, le Fil devrait atteindre la méthode CreateSprite
, ce qui bizarrement n'est pas le cas.Je ne pouvais pas comprendre pourquoi la méthode n'est pas en cours d'exécution.La forme principale de l'application fonctionne toujours très bien, mais il semble que l' EventTitle.Execute
s'arrête brusquement ou à ne pas commencer.Il pourrons peut-être misimplementation ainsi.C'est mon premier MultiThreading procès, alors désolé pour toute incohérence.N'importe qui peut voir ce que j'ai fait de mal?
La solution
Il y a quelques problèmes évidents ici.Je ne suis pas sûr que la fixation d'eux peut résoudre votre problème, mais je ne serais pas surpris:
- Votre
Execute
la méthode doit être déclarée avecoverride
pour qu'il fonctionne.C'est ce qui explique le comportement que vous signalez. - Votre destructeur doit être déclarée avec
override
pour qu'il fonctionne.Notez que vous mettre en œuvreGEvent.Destroy
mais l'GEvent
la classe de ne pas déclarer un destructeur.Donc le code en question ne compile pas. - Ne pas appeler
Terminate
dans le destructeur d'une classe thread.Le destructeur de la classe de baseTThread.Destroy
s'arrête et attend que le thread.Supprimer l'appel àTerminate
dansGEvent.Destroy
. - Votre
Terminate
méthode de cacheTThread.Terminate
.C'est vraiment une mauvaise pratique.Je suis sûr que le compilateur vous avertit de cela.Vous devez tenir compte des avertissements.Comme il est de votre fil est destructeur suspend le thread et attend qu'elle se termine.Vous feriez mieux d'espérer que le thread a déjà fini son exécution par le temps de vous détruire. - Il est inutile de créer un thread suspendu pour aussitôt reprendre.Bien qu'il n'y a pas de réel problème causé par que.
- Le code de la
GEvent.Call
est totalement bidon.Ne jamais céder àSelf
.Vous devez supprimer ce code. - Tous vos appels
Suspend
sont mauvais.Vous ne devez pas appelerSuspend
.Il a des résultats imprévisibles.Supprimer les appels àSuspend
.
Une répétition de l'erreur que vous avez fait est l'omission de override
.Ce mot clé est utilisé pour remplacer une méthode virtuelle.Dans le cas de la Execute
méthode, et le destructeur, ce sont des méthodes virtuelles appelé par une classe de base.En tant que tel, si vous ne remplacent pas la méthode virtuelle, vous êtes tout simplement l'introduction d'une nouvelle méthode dans la classe dérivée.Et quand la classe de base des appels à la méthode virtuelle, votre nouvelle méthode ne s'exécutera pas.
Je vous suggère de commencer avec ce code:
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;
J'ai supprimé la quasi totalité de votre code, mais presque toutes il a eu tort.