사용자 정의 스레드의 오작동
-
22-12-2019 - |
문제
다음 클래스가 제공됩니다.
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
종료하고 스레드를 기다립니다.다음 호출을 제거하세요.Terminate
~에GEvent.Destroy
. - 당신의
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;
거의 모든 코드를 제거했지만 거의 모든 코드가 잘못되었습니다.
제휴하지 않습니다 StackOverflow