Каков правильный способ прекратить поток с помощью Delphi для iOS при управлении ARC?
Возьмем этот простой пример:
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, и есть 2 дополнительные ссылки, которые 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).
Увидеть проблему? Thread никогда не завершается, и деструктор никогда не вызывается, если я вызываю FThread := nil
, тогда RefCount должен уменьшаться от 2 до 1 (или от 3 до 2 в случае FreeOnTerminate = FALSE
), а поток никогда не будет выпущен под ARC...
Возможно, я что-то пропустил, потому что я работал с потоками без ARC... Итак, что мне здесь не хватает? Или есть ошибка в реализации TThread в ARC?
Возможно, это определение TThread
private class threadvar
FCurrentThread: TThread;
должно быть что-то вроде
private class threadvar
[Weak] FCurrentThread: TThread;