队列不会刷新Firemonkey

时间:2017-05-15 20:24:11

标签: android windows multithreading firemonkey delphi-xe

我使用Queue在Delphi应用程序初始化中创建了许多表单,但它无法正常工作。

Bellow代码片段

TThread.Queue(TThread.CurrentThread,
         procedure()
         begin
               Application.CreateForm(TForm1, form1);
               Application.CreateForm(TForm2, form2);
               Application.CreateForm(TForm3, form3);
               .....
               Application.CreateForm(TForm9, form9);
               Application.CreateForm(TDatamodule1, datamodule1);
         end);

我希望在progressBar和label中显示创建的进度。例如: 对于最终创建的每个Tform,我设置TProgressBar.Value=TProgressBar.Value + 10,并为下一个表单更新label.text:'加载form2 ...'

该应用程序适用于Windows和Android。我在两个平台上看到的行为相同,屏幕冻结并且只是更新“加载完成”。当过程结束。我做错了什么?

注意:上次我使用Synchronize时,但我无法在TTHread上下文中创建Forms,那么必须使用Synchronize来访问全局var Form1并更新标签,这不是一个好主意。

完整的代码,

TfrmSplash.create(Sender:TObject);
begin
TThread.Queue(TThread.CurrentThread,
         procedure()
         begin
               Application.CreateForm(TForm1, form1);
               TProgressBar.Value=TProgressBar.Value + 10
               Label1.text:='Loading form2';
               Application.CreateForm(TForm2, form2);
               TProgressBar.Value=TProgressBar.Value + 10
               Label1.text:='Loading form3';
               Application.CreateForm(TForm3, form3);
               TProgressBar.Value=TProgressBar.Value + 10
               Label1.text:='Loading form4';
               .....
               Application.CreateForm(TForm9, form9);
               TProgressBar.Value=TProgressBar.Value + 10
               Label1.text:='Loading data';
               Application.CreateForm(TDatamodule1, datamodule1);
               TProgressBar.Value:=100
               Label1.text:='100% complete';
               Sleep(200);
               frmSplash.hide;
               Form1.show;
         end);
end;

1 个答案:

答案 0 :(得分:1)

您的代码存在两个问题:

  1. 您正在一次调用TThread.Queue()内执行所有UI更新,而不会在更新之间处理任何新的UI消息。主消息循环被阻止,直到排队的过程退出。这就是为什么您只看到显示最终更新消息而没有显示中间消息的原因。

  2. 请注意,在主UI线程的上下文中调用时,TThread.Queue()同步(请投票给RSP-15427 Add an option to let TThread.Queue() run asynchronously when called by the main UI thread)。因此,假设您在主线程中而不是在工作线程中创建TfrmSplash对象,则在完全创建TfrmSplash对象之前,不会显示所有UI更新。

    < / LI>

    在创建对象时,您需要让消息队列处理新消息(至少绘制消息)。您可以在创建每个对象之间调用Application.ProcessMessages()(不推荐)或启动窗体的Update()方法(首选)。

    尝试更像这样的东西:

    procedure TfrmSplash.Create(Sender: TObject);
    begin
      TThread.CreateAnonymousThread(
        procedure
        begin
          TThread.Queue(nil, CreateObjects);
        end
      ).Start;
    end;
    
    procedure TfrmSplash.SetProgress(Progress: Integer; const Text: string);
    begin
      TProgressBar.Value := Progress;
      Label1.Text := Text;
      //Application.ProcessMessages;
      Update;
    end;
    
    procedure TfrmSplash.CreateObjects;
    begin
      SetProgress(0, 'Loading form1');
      Application.CreateForm(TForm1, form1);
    
      SetProgress(10, 'Loading form2');
      Application.CreateForm(TForm2, form2);
    
      SetProgress(20, 'Loading form3');
      Application.CreateForm(TForm3, form3);
    
      SetProgress(30, 'Loading form4');
      ...
    
      SetProgress(80, 'Loading form9');
      Application.CreateForm(TForm9, form9);
    
      SetProgress(90, 'Loading data');
      Application.CreateForm(TDatamodule1, datamodule1);
    
      SetProgress(100, '100% complete');
    
      Hide;
      Form1.Show;
    end;