gpt4 book ai didi

multithreading - Delphi TTask 从主线程获取数据

转载 作者:行者123 更新时间:2023-12-02 05:30:20 26 4
gpt4 key购买 nike

根据我阅读 Nick Hodges 的理解,这段代码应该没问题:

TTask.Run(
procedure
var
resp, tmp: string;
req: boolean;
bwriter: TBinaryWriter;
myfile: TFileStream;
begin
//tell the user to wait
TThread.Queue(TThread.CurrentThread,
procedure
begin
LoginButton.Text := 'Please wait...';
end
);

//some checks
try
resp := GetURL('... here I get a result from the server...');
if (resp = fOKstatus) then
begin
req := true;

myfile := TFileStream.Create(TPath.Combine(TPath.GetHomePath, 'docs.mkb'), fmCreate);
try
bwriter := TBinaryWriter.Create(myfile, TEncoding.Unicode, false);
try
bwriter.Write(UsernameEdit.Text);
bwriter.Write(AppIDEdit.Text);
bwriter.Close;
finally
bwriter.Free;
end;
finally
myfile.Free;
end;
end
else
begin
req := false;
end;
except
req := false;
end;

//final
TThread.Queue(TThread.CurrentThread,
procedure
begin
if (req = true) then
begin
LoginButton.Text := 'Success!';
ShowMessage('Close the app to complete the registration.');
end
else
begin
LoginButton.Text := 'Login failed.';
end;
end
);

end
);

它在一个单独的线程中运行,并通过调用 Queue() 链接到主线程。事实上,一开始我使用这种方法更新按钮的Text

<小时/>

问题。看一下这两行:

bwriter.Write(UsernameEdit.Text);
bwriter.Write(AppIDEdit.Text);

我需要从主线程 UI 中的两个编辑控件中检索用户名和 AppID(这是一个随机代码)。这是正确的吗?

我想我应该调用Queue(),但到目前为止程序运行良好。

我可以安全地以这种方式获取这些值吗?我没有更新任何内容,我只需要获取数据,但我不确定混合来自两个不同任务的内容是否会是危险/不好的做法。

最佳答案

您关心的两行代码不是线程安全的。您必须与主线程同步才能进行所有 UI 访问(包括读取和写入)。 TThread.Queue()异步,因此它不适合从 UI 检索值的目的。使用 TThread.Synchronize() 代替,这是同步:

TTask.Run(
procedure
var
resp, tmp, username, appid: string;
req: boolean;
bwriter: TBinaryWriter;
myfile: TFileStream;
begin
//tell the user to wait
TThread.Queue(nil,
procedure
begin
LoginButton.Text := 'Please wait...';
end
);

//some checks
try
resp := GetURL('... here I get a result from the server...');
if resp = fOKstatus then
begin
req := true;

TThread.Synchronize(nil,
procedure
begin
username := UsernameEdit.Text;
appid := AppIDEdit.Text;
end
);

myfile := TFileStream.Create(TPath.Combine(TPath.GetHomePath, 'docs.mkb'), fmCreate);
try
bwriter := TBinaryWriter.Create(myfile, TEncoding.Unicode, false);
try
bwriter.Write(username);
bwriter.Write(appid);
bwriter.Close;
finally
bwriter.Free;
end;
finally
myfile.Free;
end;
end
else
begin
req := false;
end;
except
req := false;
end;

//final
TThread.Queue(nil,
procedure
begin
if req then
begin
LoginButton.Text := 'Success!';
ShowMessage('Close the app to complete the registration.');
end
else
begin
LoginButton.Text := 'Login failed.';
end;
end
);
end
);

或者,假设主 UI 线程是启动 TTask 的线程,您可以在启动 TTask 之前读取这 2 个值,并让匿名过程捕获它们:

var
username, appid: string;
begin
username := UsernameEdit.Text;
appid := AppIDEdit.Text;

TTask.Run(
procedure
var
resp, tmp: string;
req: boolean;
bwriter: TBinaryWriter;
myfile: TFileStream;
begin
//tell the user to wait
TThread.Queue(nil,
procedure
begin
LoginButton.Text := 'Please wait...';
end
);

//some checks
try
resp := GetURL('... here I get a result from the server...');
if resp = fOKstatus then
begin
req := true;

myfile := TFileStream.Create(TPath.Combine(TPath.GetHomePath, 'docs.mkb'), fmCreate);
try
bwriter := TBinaryWriter.Create(myfile, TEncoding.Unicode, false);
try
bwriter.Write(username);
bwriter.Write(appid);
bwriter.Close;
finally
bwriter.Free;
end;
finally
myfile.Free;
end;
end
else
begin
req := false;
end;
except
req := false;
end;

//final
TThread.Queue(nil,
procedure
begin
if req then
begin
LoginButton.Text := 'Success!';
ShowMessage('Close the app to complete the registration.');
end
else
begin
LoginButton.Text := 'Login failed.';
end;
end
);
end
);
end;

关于multithreading - Delphi TTask 从主线程获取数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42496767/

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