Multithreading 如何在TThread中而不是在FMX的主进程中启用AniIndicator1?
嗨,我有一个基于FMX的多设备应用程序 同步数据库过程需要更长的时间,我需要启用一个指示符号1来告诉用户等待 下面的代码在n安卓手机上测试,有时有效,有时只完成第一个同步DB功能,有时完成前3个,然后退出。有时,sychDB功能没有发生Multithreading 如何在TThread中而不是在FMX的主进程中启用AniIndicator1?,multithreading,delphi,cursor,firemonkey,Multithreading,Delphi,Cursor,Firemonkey,嗨,我有一个基于FMX的多设备应用程序 同步数据库过程需要更长的时间,我需要启用一个指示符号1来告诉用户等待 下面的代码在n安卓手机上测试,有时有效,有时只完成第一个同步DB功能,有时完成前3个,然后退出。有时,sychDB功能没有发生 procedure TForm1.BtnSyncDBClick(Sender: TObject); begin Application.ProcessMessages; memo3.Lines.Add('Start synchronising...')
procedure TForm1.BtnSyncDBClick(Sender: TObject);
begin
Application.ProcessMessages;
memo3.Lines.Add('Start synchronising...');
AniIndicator1.Visible:=true;
AniIndicator1.Enabled:=true;
TThread.CreateAnonymousThread(
procedure
begin
try
SynchDB_A;
memo3.Lines.Add('finish 0');
SynchDB_B;
memo3.Lines.Add('finish 1');
SynchDB_C ;
memo3.Lines.Add('finish 2');
SynchDB_D;
memo3.Lines.Add('finish 3');
finally
AniIndicator1.Enabled := False;
AniIndicator1.Visible := False;
end;
end
).start;
end;
因此,我想知道是否可以将AniIndicator1.enable函数放在子线程中,并使用主线程来同步HDB
尝试了以下代码,但未按预期工作
procedure TForm1.BtnSyncDBClick(Sender: TObject);
begin
TThread.CreateAnonymousThread(
procedure
begin
try
TThread.Synchronize (TThread.CurrentThread,
procedure ()
begin
Memo1.lines.Add('Start... ');
AniIndicator1.Visible := True;
AniIndicator1.Enabled := True;
end);
finally
end;
end
).Start;
try
SynchDB_A;
memo3.Lines.Add('finish 0');
SynchDB_B;
memo3.Lines.Add('finish 1');
SynchDB_C ;
memo3.Lines.Add('finish 2');
SynchDB_D;
memo3.Lines.Add('finish 3');
finally
AniIndicator1.Enabled := False;
AniIndicator1.Visible := False;
end;
end;
任何专家都可以对此提供帮助,要么修复第一个代码以确保始终工作,子线程不会被终止,要么在主进程中启动SynchDB并在子线程中启用AniIndicator1并使其旋转。或者其他简单的方法告诉用户在synchDB工作时等待
提前感谢。您不能像现在这样直接从工作线程中访问UI控件。您必须将该访问同步到主UI线程
过程TForm1.BtnSyncDBClick(发送方:TObject);
变量
线程:TThread;
开始
Application.ProcessMessages;
备忘录3.行。添加('开始同步…');
aniindicator 1.可见:=真;
AniIndicator1.Enabled:=真;
线程:=TThread.CreateAnonymousThread(
程序
开始
SynchDB_A;//您不能像现在这样直接从工作线程中访问UI控件。您必须将该访问同步到主UI线程
过程TForm1.BtnSyncDBClick(发送方:TObject);
变量
线程:TThread;
开始
Application.ProcessMessages;
备忘录3.行。添加('开始同步…');
aniindicator 1.可见:=真;
AniIndicator1.Enabled:=真;
线程:=TThread.CreateAnonymousThread(
程序
开始
SynchDB_A;//为什么在onclick事件中调用application.processmessages?
您已经在主线程消息循环中
您还可以使用TTask.run,它比TThread.CreateAnonymousThread更简单
TTask.run(
procedure
var
msg : string;
begin
try
SynchDB_A;
msg:='finish 1';
except
on e:exception do begin
msg:=e.message;
end;
end;
TThread.Queue(Nil,
procedure
begin
memo3.lines.add(msg);
end);
为什么在onclick事件中调用application.processmessages?
您已经在主线程消息循环中
您还可以使用TTask.run,它比TThread.CreateAnonymousThread更简单
TTask.run(
procedure
var
msg : string;
begin
try
SynchDB_A;
msg:='finish 1';
except
on e:exception do begin
msg:=e.message;
end;
end;
TThread.Queue(Nil,
procedure
begin
memo3.lines.add(msg);
end);
试试这个,创建这个过程
procedure TFDashboard.fnLoading(isEnabled : Boolean);
begin
TThread.Synchronize(nil, procedure begin
AniIndicator1.Visible := isEnabled;
AniIndicator1.Enabled := isEnabled;
end);
end;
之后,您可以在TTask内部调用该过程
procedure TFDashboard.FirstShow;
begin
TTask.Run(procedure begin
fnLoading(True);
try
finally
fnLoading(False);
end;
end).Start;
end;
试试这个,创建这个过程
procedure TFDashboard.fnLoading(isEnabled : Boolean);
begin
TThread.Synchronize(nil, procedure begin
AniIndicator1.Visible := isEnabled;
AniIndicator1.Enabled := isEnabled;
end);
end;
之后,您可以在TTask内部调用该过程
procedure TFDashboard.FirstShow;
begin
TTask.Run(procedure begin
fnLoading(True);
try
finally
fnLoading(False);
end;
end).Start;
end;
感谢您的评论。您的代码(与我的第一个版本类似)的问题在于,并非所有synchDB函数都将被执行。有时仅执行1,备忘录1只有一行“完成0”,然后工作线程完成了。问题出在哪里?这也发生在Windows平台上。我发现了问题。synchDB有错误。因此它安静地结束。将尝试..最后异常可以在工作线程中显示错误消息?@Haizhou如果工作线程引发异常但未捕获,线程将简单地终止。如果要对异常执行任何操作,您需要捕获异常。在这种情况下,由于您使用的是TThread
,因此可以为该线程分配OnTerminate
处理程序,并检查其FatalException
属性。您还可以使用此事件停止TAniIndicator
,因此不需要tryy
不再。我已经更新了我的示例来说明这一点。你是一个明星,谢谢你的想法。你能给出一个TTHread.OnTerminate编码的简短示例吗?不知道如何实现它。@Haizhou看到我的更新示例谢谢你的评论。你的代码的问题(类似于我的第一个版本)并非所有synchDB函数都将执行。有时仅执行1,Memo1只有一行“完成0”,然后工作线程完成了。问题出在哪里?这也发生在Windows平台上。我发现了问题。synchDB有错误。因此它安静地结束。将尝试..最后异常可以在工作线程中显示错误消息?@Haizhou如果工作线程引发异常但未捕获,线程将简单地终止。如果要对异常执行任何操作,您需要捕获异常。在这种情况下,由于您使用的是TThread
,因此可以为该线程分配OnTerminate
处理程序,并检查其FatalException
属性。您还可以使用此事件停止TAniIndicator
,因此不需要tryy
不再。我已经更新了我的示例来说明这一点。你是一个明星,谢谢你的想法。你能给出一个关于TTHread.OnTerminate编码的简短示例吗?不知道如何实现它。@Haizhou看到我更新的示例了吗