Как я могу установить внешнюю переменную на ноль внутри метода?
Я хотел бы подкласс TThread
для того, чтобы иметь класс потока, который, когда FreeOnTerminate = True
устанавливает nil
его ссылочная переменная. Другими словами, я хочу сделать что-то вроде этого:
TFreeAndNilThread = class(TThread)
private
FReferenceObj: TFreeAndNilThread; //?? // <-- here I'm holding the reference to myself
protected
procedure Execute;
procedure DoTerminate; override; // <-- here I'll set FReferenceObj to nil after inherited (only if FreeAndNil = True)
public
constructor Create(CreateSuspended: Boolean; var ReferenceObj); reintroduce; <-- untyped param like FreeAndNil and TApplication.CreateForm ??
end;
Код потребителя должен быть таким:
var
MyThread: TFreeAndNilThread;
begin
MyThread := TFreeAndNilThread.Create(True, MyThread);
MyThread.FreeOnTerminate := True;
MyThread.Resume;
end;
... и тогда я смог бы безопасно проверить Assigned(MyThread)
,
Я вижу как FreeAndNil
удается установить ссылочный объект, переданный нетипизированным параметром nil
, но это делает это локально. В моем случае я должен "сохранить" его в поле класса (FReferenceObj
) и сделать это ноль в другом месте (DoTerminate
).
Как я могу правильно передать, сохранить и получить его? Я могу думать о передаче и сохранении адреса MyThread вместо самого MyThread, но я надеюсь, что есть более элегантный способ.
Спасибо!
1 ответ
Вам нужно сохранить указатель на переменную.
type
TFreeAndNilThread = class(TThread)
private
FReferenceObj: ^TFreeAndNilThread;
end;
Затем вам нужно передать ссылку в конструкторе:
type
TFreeAndNilThread = class(TThread)
private
FReferenceObj: ^TFreeAndNilThread;
public
constructor Create(var ReferenceObj: TFreeAndNilThread);
end;
Тогда вы можете реализовать это так:
constructor TFreeAndNilThread.Create(var ReferenceObj: TFreeAndNilThread);
begin
inherited Create(True);
FreeOnTerminate := True;
FReferenceObj := @ReferenceObj;
end;
Когда поток умирает, вы устанавливаете ссылку на nil
как это:
ReferenceObj^ := nil;
Для удобства, поскольку вы, скорее всего, будете рассматривать это как базовый класс, из которого вы производите другие классы, вы можете предпочесть сделать параметр для конструктора нетипизированным. Вы можете просто сделать это без внесения других изменений в код. Когда вы это делаете, конструктор выглядит так:
constructor Create(var ReferenceObj);
Это пойдет вам на пользу, только если код, который устанавливает ссылку на nil
находится в том же потоке, что и весь другой код, который пытается ссылаться MyThread
, В противном случае у вас будет состояние гонки.
Я вполне уверен, что ваша идея не является решением вашей проблемы. Однако вышеприведенное показывает, как получить ссылку на переменную, о чем вы просили.