gpt4 book ai didi

delphi - TThread本身的线程安全字段是线程安全的吗?

转载 作者:行者123 更新时间:2023-12-03 15:19:08 24 4
gpt4 key购买 nike

在此代码中:

TMyClass = class(TThread)
public
FInputBuffer : TThreadedQueue<TBytes>;
protected
procedure Execute; override;
end;

FInputBuffer 的使用(在 TMyClass 和其他类中)是线程安全的吗?

编辑:

示例使用:在 TMyClass 中:

procedure TMyClass.Execute;
var x :TBytes;
begin
inherited;
FInputBuffer:= TThreadedQueue<TBytes>.Create;
while not Terminated do begin
if FInputBuffer.QueueSize > 0 then begin
x:= FInputBuffer.PopItem;
//some code to use x
end;
end;
FInputBuffer.Free;
end;

在其他类(class)中:

var MyClass :TMyClass ;

procedure TForm1.btn1Click(Sender: TObject);
var x :TBytes;
begin
//set x
MyClass.FInputBuffer.PushItem(x);
end;

最佳答案

如果FInputBuffer在线程开始运行之前在线程构造函数中创建,并在线程结束后在线程析构函数中释放运行,那么是的,当 TMyClass 对象仍然存在时,从其他线程访问它是线程安全的,因为 TThreadedQueue 为其内部内容提供了自己的线程安全性。您所展示的是多线程队列的完全有效使用,前提是 MyClass 变量在调用 btn1Click() 时有效。

但是,如果 FInputBufferExecute() 内部创建的,那么它不是线程安全的,因为在创建 FInputBuffer 之前,btn1Click() 可能会在线程开始运行之前尝试访问队列。这就是为什么您需要在构造函数中创建 FInputBuffer ,例如:

TMyClass = class(TThread)
public
FInputBuffer: TThreadedQueue<TBytes>;
constructor Create(ACreateSuspended: Boolean); override;
destructor Destroy; override;
protected
procedure Execute; override;
end;

constructor TMyClass.Create(ACreateSuspended: Boolean);
begin
inherited;
FInputBuffer := TThreadedQueue<TBytes>.Create;
end;

destructor TMyClass.Destroy;
begin
FInputBuffer.Free;
inherited;
end;

procedure TMyClass.Execute;
var
x: TBytes;
begin
while not Terminated do begin
if FInputBuffer.QueueSize > 0 then begin
x := FInputBuffer.PopItem;
// some code to use x
end;
end;
end;

如果您想在 Execute() 内部创建 FInputBuffer,那么线程应该公开一个在 FInputBuffer 之后设置的标志/信号实际上已创建,然后在设置该标志/信号之前,任何其他代码都不应尝试访问 FInputBuffer。创建线程实例的代码应该等待该标志/信号,然后再将控制权返回给代码的其余部分,例如:

TMyClass = class(TThread)
public
FInputBuffer: TThreadedQueue<TBytes>;
FInputBufferCreated: TEvent;
constructor Create(ACreateSuspended: Boolean); override;
destructor Destroy; override;
protected
procedure Execute; override;
procedure DoTerminate; override;
end;

constructor TMyClass.Create(ACreateSuspended: Boolean);
begin
inherited;
FInputBufferCreated := TEvent.Create(nil, True, False, '');
end;

destructor TMyClass.Destroy;
begin
FInputBufferCreated.Free;
inherited;
end;

procedure TMyClass.Execute;
var
x: TBytes;
begin
FInputBuffer := TThreadedQueue<TBytes>.Create;
FInputBufferCreated.SetEvent;

while not Terminated do begin
if FInputBuffer.QueueSize > 0 then begin
x := FInputBuffer.PopItem;
// some code to use x
end;
end;
end;

procedure TMyClass.DoTerminate;
begin
if FInputBufferCreated <> nil then
FInputBufferCreated.ResetEvent;
FreeAndNil(FInputBuffer);
inherited;
end;

.

var
MyClass: TMyClass = nil;

procedure TForm1.StartBufferThread;
var
I: Integer;
begin
MyClass := TMyClass.Create(False);
if MyClass.FInputBufferCreated.WaitFor(2500) <> wrSignaled then
begin
MyClass.Terminate;
MyClass.WaitFor;
FreeAndNil(MyClass);
raise Exception.Create('MyClass.FInputBuffer not created after 2.5 seconds!');
end;
end;

procedure TForm1.btn1Click(Sender: TObject);
var
x: TBytes;
begin
//set x
if MyClass <> nil then
MyClass.FInputBuffer.PushItem(x);
end;

关于delphi - TThread本身的线程安全字段是线程安全的吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16425811/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com