- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
根据我阅读 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/
有人可以向我澄清主线 DHT 规范中的声明吗? Upon inserting the first node into its routing table and when starting up th
我正在尝试使用 USB 小工具驱动程序使嵌入式设备作为 MTP 设备工作。 我知道 Android 从大容量存储设备切换到 MTP 设备已经有一段时间了,并且找到了 source code for M
我是一名优秀的程序员,十分优秀!