给定以下类(class):
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;
当主窗体自动调用InstanceVar := EventTitle.Create
时,线程应该到达方法CreateSprite
,但奇怪的是没有发生。我不明白为什么该方法没有被执行。应用程序的主要形式仍然工作正常,但似乎 EventTitle.Execute
突然停止,甚至没有启动。这也可能是错误实现。这是我第一次尝试多线程,对于任何不一致之处深表歉意。谁能看到我做错了什么吗?
最佳答案
这里存在一些明显的问题。我不确定修复它们能否解决您的问题,但我不会感到惊讶:
- 您的
Execute
方法必须使用override
声明才能运行。这解释了您报告的行为。 - 您的析构函数必须使用
override
声明才能运行。请注意,您实现了 GEvent.Destroy,但 GEvent 类未声明析构函数。所以问题中的代码无法编译。 - 不要在线程类的析构函数中调用
Terminate
。基类析构函数TThread.Destroy
终止并等待线程。在GEvent.Destroy
中删除对Terminate
的调用。 - 您的
Terminate
方法隐藏了TThread.Terminate
。这确实是很糟糕的做法。我确信编译器会警告你这一点。您必须留意警告。按照目前的情况,线程的析构函数会挂起线程,然后等待它完成。您最好希望在销毁线程时该线程已经执行完毕。 - 创建一个挂起的线程只是为了立即恢复它是没有意义的。尽管这不会造成真正的问题。
GEvent.Call
中的代码完全是伪造的。切勿分配给Self
。您必须删除该代码。- 您对
Suspend
的所有调用都是错误的。您不得调用Suspend
。它会产生不可预测的结果。删除对Suspend
的调用。
您重复犯的错误是遗漏了override
。该关键字用于覆盖虚拟方法。对于 Execute 方法和析构函数,这些是由基类调用的虚拟方法。因此,如果不重写虚拟方法,则只需在派生类中引入一个新方法。而当基类调用虚方法时,你的新方法将不会执行。
我建议您从以下代码开始:
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;
我已经删除了几乎所有代码,但几乎所有代码都是错误的。
关于multithreading - 自定义线程行为不当,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21050766/