2017-05-15 4 views
-2

J'utilise Queue pour créer plusieurs Forms lors de l'initialisation de l'application Delphi, mais cela ne fonctionne pas correctement.La file d'attente n'actualise pas la barre de progression sur Firemonkey

Bellow un fragment de code de

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); 

J'espère montrer les progrès de la création dans un progressBar et l'étiquette. Par exemple: Pour chaque tform finalement créé, je mis TProgressBar.Value=TProgressBar.Value + 10, et mise à jour label.text pour la forme suivante: 'chargement form2 ...'

L'apllication fonctionne sous Windows et Android. Le même comportement que je vois dans les deux plate-forme, L'écran se fige et juste mettre à jour «chargement complet» lorsque le processus se termine. Qu'est-ce que je fais mal?


Note: La dernière fois que j'utilisais Synchronize, mais je ne pouvais pas créer des formulaires sur le contexte TThread, alors Synchronize était nécessaire pour accéder à l'étiquette globale var Form1 et mise à jour, qui n'a pas été bonne idée.

Le code complet,

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; 
+0

XE ne supporte pas Android ou FireMonkey. Il est parfois utile de savoir quelle version vous utilisez. Soyez précis au sujet de ces détails. J'ai expliqué beaucoup de ceci à votre dernière question. Il est important pour vous d'en tenir compte. En ce qui concerne la question, nous avons vraiment besoin d'une image claire du contexte dans lequel ce code s'exécute. Alors, veuillez fournir un [mcve]. –

+0

Vous avez tort, Firemonkey et Android sont pris en charge depuis Delphi Xe2. Le code fonctionne en xe7, xe5 et xe2. Je vais améliorer le code pour vous m'aider. –

+0

XE est la version antérieure à XE2. Il cible uniquement Windows. Nous avons besoin d'un [mcve]. S'il vous plaît en fournir un. –

Répondre

1

Il y a deux problèmes avec votre code:

  1. vous effectuez toutes vos mises à jour de l'interface utilisateur dans un seul appel à TThread.Queue() sans traitement de nouveaux messages de l'interface utilisateur entre les mises à jour. La boucle du message principal est bloquée jusqu'à la fin de la procédure en file d'attente. C'est pourquoi vous ne voyez que votre message de mise à jour finale et aucun des messages intermédiaires.

  2. Notez que TThread.Queue() est synchrone lorsqu'il est appelé dans le contexte du thread principal de l'interface utilisateur (s'il vous plaît voter pour RSP-15427 Add an option to let TThread.Queue() run asynchronously when called by the main UI thread). Ainsi, en supposant que vous créez votre objet TfrmSplash dans le thread principal et non dans un thread de travail, toutes vos mises à jour de l'interface utilisateur ne seront pas affichées tant que l'objet TfrmSplash n'aura pas été entièrement créé.

Vous devez laisser la file d'attente de messages traiter de nouveaux messages (au moins la peinture des messages) pendant que vous créez vos objets. Vous pouvez appeler Application.ProcessMessages() (non recommandé) ou la méthode Update() du formulaire de démarrage (de préférence) entre la création de chaque objet.

Essayez quelque chose comme ceci:

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; 
+0

Merci beaucoup. C'est tout ce dont j'ai besoin. En effet, processMessages n'est pas autorisé dans Firemonkey, je pense. –