Benutzerdefinierter Thread verhält sich schlecht
-
22-12-2019 - |
Frage
Angesichts der folgenden Klassen:
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;
Wenn das Hauptformular aufruft InstanceVar := EventTitle.Create
automatisch sollte der Thread die Methode erreichen CreateSprite
, was seltsamerweise nicht passiert.Ich konnte nicht verstehen, warum die Methode nicht ausgeführt wird.Die Hauptform der Anwendung funktioniert immer noch einwandfrei, aber es scheint so EventTitle.Execute
stoppt abrupt oder startet gar nicht.Möglicherweise handelt es sich auch um eine Fehlimplementierung.Es ist mein erster MultiThreading-Versuch, bitte entschuldigen Sie etwaige Unstimmigkeiten.Kann jemand sehen, was ich falsch gemacht habe?
Lösung
Hier gibt es einige offensichtliche Probleme.Ich bin mir nicht sicher, ob die Behebung Ihr Problem lösen wird, würde mich aber nicht wundern:
- Dein
Execute
Methode muss mit deklariert werdenoverride
damit es läuft.Dies erklärt das von Ihnen gemeldete Verhalten. - Ihr Destruktor muss mit deklariert werden
override
damit es läuft.Beachten Sie, dass Sie implementierenGEvent.Destroy
aber dieGEvent
Die Klasse deklariert keinen Destruktor.Der Code in der Frage lässt sich also nicht kompilieren. - Ruf nicht an
Terminate
im Destruktor einer Thread-Klasse.Der Destruktor der BasisklasseTThread.Destroy
beendet sich und wartet auf den Thread.Entfernen Sie den Anruf anTerminate
InGEvent.Destroy
. - Dein
Terminate
Methode verbirgt sichTThread.Terminate
.Das ist wirklich eine schlechte Praxis.Ich bin sicher, dass der Compiler Sie davor warnt.Sie müssen die Warnungen beachten.So wie es aussieht, hält der Destruktor Ihres Threads den Thread an und wartet dann darauf, dass er beendet wird.Sie sollten besser hoffen, dass die Ausführung des Threads bereits abgeschlossen ist, wenn Sie ihn zerstören. - Es ist sinnlos, einen angehaltenen Thread zu erstellen, um ihn dann sofort fortzusetzen.Obwohl es kein wirkliches Problem gibt, das dadurch verursacht wird.
- Der Code in
GEvent.Call
ist völliger Blödsinn.Nie zuweisenSelf
.Sie müssen diesen Code entfernen. - Alle Ihre Anrufe an
Suspend
sind falsch.Sie dürfen nicht anrufenSuspend
.Es hat unvorhersehbare Ergebnisse.Entfernen Sie die Anrufe anSuspend
.
Ein wiederholter Fehler, den Sie gemacht haben, ist das Auslassen von override
.Dieses Schlüsselwort wird verwendet, um eine virtuelle Methode zu überschreiben.Im Fall der Execute
Methode und Destruktor sind virtuelle Methoden, die von einer Basisklasse aufgerufen werden.Wenn Sie also die virtuelle Methode nicht überschreiben, führen Sie lediglich eine neue Methode in der abgeleiteten Klasse ein.Und wenn die Basisklasse die virtuelle Methode aufruft, wird Ihre neue Methode nicht ausgeführt.
Ich schlage vor, dass Sie mit diesem Code beginnen:
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;
Ich habe fast Ihren gesamten Code entfernt, aber fast alles war falsch.