- 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/
单击按钮后,我创建 3 个任务,每个任务都有空过程,并将方法调用和任务列表完成的时间差写入控制台: procedure TWinTest.BtnThreadTestClick(Sender: TObj
根据我阅读 Nick Hodges 的理解,这段代码应该没问题: TTask.Run( procedure var resp, tmp: string; req: boolea
专家,请看下面的代码片段: var aAllTasks : Array [0..1] of ITask //global private var Procedure SetImage(); be
我不知道如何在 Delphi 中正确使用 TTask。 我创建了一个 TTask。 syncTask := ttask.Create(SyncMysqlDatabase); 以下代码在onlocati
我对线程的经验有限。我想并行读取一些基本的数据库表,我需要等到所有表都读取完,程序才能合理地进行。在这方面,阻塞主线程对我来说没问题。 此代码(简化版)工作正常: procedure ReadDBMu
我有以下两种多线程代码方法来完成相同的工作。 任务: const MaxThreadCount = 80; procedure TWorkerTask.Update; var aTasks
Delphi 中的匿名方法创建一个闭包,该闭包在上下文中保持“包围”局部变量,直到匿名方法完成。如果使用接口(interface)变量,那么它们将在匿名方法完成之前减少其引用的实例。到目前为止一切顺利
背景 使用 TThread.CreateANonymousThread(aProc:TProc)我可以创建一个线程,在线程终止后销毁线程对象。 (或者将 FreeOnTerminate 设置为 tru
这是我在 DLL 中的代码: procedure TTaskTest; begin TTask.Run( procedure begin Sleep(300);
我是一名优秀的程序员,十分优秀!