ARC 관리에서 iOS 용 Delphi를 사용하여 스레드를 종료하는 적절한 방법은 무엇입니까? ARC (iOS)에서 Delphi TThread가 출시되지 않음
이 간단한 예를 들어 보자TMyThread = class(TThread)
protected
procedure Execute; override;
public
destructor Destroy; override;
end;
TForm2 = class(TForm)
Button1: TButton;
Button2: TButton;
Button3: TButton;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
private
FThread: TMyThread;
public
end;
{ TMyThread }
destructor TMyThread.Destroy;
begin
ShowMessage('Destroy');
inherited Destroy;
end;
procedure TMyThread.Execute;
begin
Sleep(5000);
end;
{ TForm2 }
procedure TForm2.Button1Click(Sender: TObject);
begin
FThread := TMyThread.Create(TRUE);
FThread.FreeOnTerminate := TRUE;
FThread.Start;
end;
procedure TForm2.Button2Click(Sender: TObject);
begin
ShowMessage(FThread.RefCount.ToString);
end;
procedure TForm2.Button3Click(Sender: TObject);
begin
FThread := nil;
end;
가 좋아, Button1을이 스레드를 생성 누르면. 스레드가 시작된 후 Button2를 클릭하면 RefCount 값이 3으로 표시됩니다 !! 음, 1 내 FThread 변수에 대한 참조이며, TThread은 내부적으로 생성이 추가 참조가 ... 나는 소스 코드에 팠하고 refcount는 여기에 증가되는 것을 발견 : 여기
constructor TThread.Create(CreateSuspended: Boolean);
ErrCode := BeginThread(nil, @ThreadProc, Pointer(Self), FThreadID);
if ErrCode <> 0 then
raise EThread.CreateResFmt(@SThreadCreateError, [SysErrorMessage(ErrCode)]);
{$ENDIF POSIX}
과 :
function ThreadProc(Thread: TThread): Integer;
var
FreeThread: Boolean;
begin
TThread.FCurrentThread := Thread;
글쎄 ... 스레드가 완료된 후 (내 경우 5 초 후) RefCount가 2로 감소합니다 (FreeOnTerminate를 TRUE로 설정했기 때문에 FreeOnTerminate를 TRUE로 설정하지 않으면 RefCount는 여전히 3)입니다.
문제점을 확인하십시오. 스레드가 끝나지 않고 소멸자가 호출되지 않습니다. FThread := nil
을 호출하면 RefCount가 2에서 1로 (또는 FreeOnTerminate = FALSE
의 경우 3에서 2로) 감소하고 ARC에서 스레드가 절대로 해제되지 않습니다.
아마도 ARC가없는 스레드로 작업하는 데 익숙해 졌기 때문에 뭔가 빠졌을 것입니다 ... 그래서 여기에 무엇을 놓치고 있습니까? 또는 ARC에서 TThread 구현에 버그가 있습니까? 다음과 같은 문제 및 해결 방법 품질 관리의 뒷조사 후
private class threadvar
[Weak] FCurrentThread: TThread;
'FCurrentThread'가 소멸자에서 해제되지 않았습니까? –
FCurrentThread는 TThread의 클래스 threadvar 변수이며 인스턴스의 변수는 아니지만 TThread의 클래스 변수입니다. 이 변수는 절대로 바뀌지 않습니다. 코드로 판단하면 다른 스레드를 생성하면 바뀌어야하지만 ... 테스트되지는 않습니다. 그래서 ... 내 스레드 소멸자는 호출되지 않습니다 – Eric
다른 스레드를 생성하여 변경되지 않습니다. 각 OS 스레드는 threadvar이기 때문에 해당 변수의 자체 버전을 가져옵니다. GetCurrentThreadID와 동일한 TThread입니다. –