Пользовательский поток ведет себя неправильно

StackOverflow https://stackoverflow.com//questions/21050766

Вопрос

Учитывая следующие классы:

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 резко останавливается или даже не запускается.Это может быть и неправильная реализация.Это мое первое испытание многопоточности, прошу прощения за несоответствия.Может ли кто-нибудь увидеть, что я сделал не так?

Это было полезно?

Решение

Здесь есть некоторые очевидные проблемы.Я не уверен, что их исправление решит вашу проблему, но я бы не удивился:

  1. Твой Execute метод должен быть объявлен с помощью override чтобы оно работало.Это объясняет поведение, о котором вы сообщаете.
  2. Ваш деструктор должен быть объявлен с помощью override чтобы оно работало.Обратите внимание, что вы реализуете GEvent.Destroy но GEvent класс не объявляет деструктор.Таким образом, код в вопросе не компилируется.
  3. Не звони Terminate в деструкторе класса потока.Деструктор базового класса TThread.Destroy завершается и ждет потока.Удалить вызов на Terminate в GEvent.Destroy.
  4. Твой Terminate метод скрывает TThread.Terminate.Это действительно плохая практика.Я уверен, что компилятор вас об этом предупреждает.Вы должны прислушаться к предупреждениям.В нынешнем виде деструктор вашего потока приостанавливает поток, а затем ждет его завершения.Вам лучше надеяться, что поток уже завершит выполнение к моменту его уничтожения.
  5. Бессмысленно создавать приостановленный поток только для того, чтобы немедленно возобновить его.Хотя никакой реальной проблемы из-за этого не будет.
  6. Код в GEvent.Call является совершенно фальшивым.Никогда не назначайте Self.Вы должны удалить этот код.
  7. Все ваши звонки на 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;

Я удалил почти весь ваш код, но почти весь он был неверным.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top