2014-01-10 23 views
3

考虑以下类:自定义线行为不端

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突然停止,甚至不启动。它可能也是错误实现。这是我的第一个多线程试用版,然后对任何不一致性抱歉。任何人都可以看到我做错了什么?

+0

OT:不要使用暂停和恢复。当编译器在警告中报告你时,它们已被废弃......同时创建线程作为立即恢复的暂停状态看起来并不太有用。 – TLama

+0

真的。我会让'Resume'给子线程。删除它...... – Guill

+0

也许使用OmniThreadLibrary对你来说比对TThread内部进行挖掘更容易 –

回答

5

这里有一些明显的问题。我不知道,修复它们能够解决您的问题,但我也不会感到惊讶:

  1. Execute方法必须与override声明为它运行。这解释了你报告的行为。
  2. 您的析构函数必须声明为override才能运行。请注意,你实现了GEvent.Destroy,但GEvent类没有声明析构函数。所以问题中的代码不能编译。在线程类的析构函数中不要调用Terminate。基类析构函数TThread.Destroy终止并等待该线程。取消拨打电话TerminateGEvent.Destroy。您的Terminate方法隐藏TThread.Terminate。这是非常糟糕的做法。我确信编译器会警告你。你必须注意警告。按照它的规定,线程的析构函数暂停线程,然后等待它完成。你最好希望线程在你销毁它的时候已经完成了执行。
  3. 创建一个线程仅仅是为了立即恢复它是没有意义的。虽然没有真正的问题会由此造成的。
  4. GEvent.Call中的代码完全是假的。永远不要分配到Self。您必须删除该代码。
  5. 您拨打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; 

我已经去掉了几乎所有的代码,但几乎所有的这是不对的。

+0

1.好吧。 2.“GEvent”将有许多孩子;其中一些可能需要一些初始化的东西。但是,这里也一样。 3。此代码引用另一个具有“GEvent”属性的类。这个属性会在使用'Call'方法的事件之间改变,但我正在努力去除那条线。这不是问题的原因。 4.所有“暂停”呼叫被移除。问题依然存在。 – Guill

+0

答案已更新。阅读新的项目1. –

+0

我猜'Override'丢失了。曾经我认为我不需要在孩子身上做的“GEvent”课程。我还没有在关于Delphi的Threading的页面中找到这个惯例。他们是非常必要的。无论如何,谢谢你,先生。我接受你的答案。我还不能投票,所以... – Guill