1
votes

(Delphi fmx) Pouvez-vous créer des contrôles d'interface utilisateur dans un thread d'arrière-plan sans bloquer l'interface utilisateur

Je me demande s'il est possible de créer des éléments d'interface utilisateur, même un formulaire complet, dans un thread d'arrière-plan ("sans l'utiliser bien sûr"), et une fois que c'est fait, le rendre disponible dans le thread principal pour être affiché.

p> Il est relativement facile maintenant de séparer les opérations de données chronophages dans les threads d'arrière-plan et de synchroniser les résultats avec votre thread principal, mais que se passe-t-il si la création de l'interface utilisateur elle-même est l'opération qui prend du temps?

Si possible, vous pourriez peut-être avoir un écran de démarrage rapide, puis démarrer un fil d'arrière-plan pour créer un ensemble de formulaires. Chaque fois que l'on est prêt, il active un élément de menu dans le thread principal pour qu'il puisse être utilisé.

J'ai essayé du code simple, mais il se fige immédiatement. Est-ce possible?

Exécuter dans le programme principal:

    ...
    // declare var in main form 
    public
     { Public declarations }
     lForm : TForm ;

    ...
    // Execute e.g. with button click in main form 
    TThread.CreateAnonymousThread( procedure begin
    // this stops application from running when the form is show
    // in the synchronize part
    lForm := TForm1.Create(Self);

    TThread.Synchronize(nil,
     procedure begin
       // This does not stops the application but freezes the gui of course
       //lForm := TForm1.Create(Self);
       lForm.Parent := Self ;
       lForm.Show ;
      end );

   end ).Start ;`


    procedure TForm1.FormCreate(Sender: TObject);
    begin
     sleep(2000);
    end;
    ...



Si ce n'est pas possible, comment pouvez-vous faire cela dans le thread principal tout en «simulant» que votre thread principal est réactif? (en appelant quelque chose comme application.processmessages régulièrement ou plus?)

J'utilise Delphi Rio 10.3, le framework fmx.


12 commentaires

La création de contrôles d'interface utilisateur n'est pas votre goulot d'étranglement


" Et si la création de l'interface utilisateur elle-même est une opération qui prend du temps? " - alors vous avez une conception de l'interface utilisateur très mauvaise


Bien que la question soit générique (je peux penser à certains cas d'utilisation), mon problème actuel dans la `` vraie vie '' est avec twebbrowser..Créer cela ne prend pas beaucoup de temps, mais définir l'URL sur un fichier html local avec vidéo intégrée les balises prennent quelques secondes à se charger. Donc, idéalement, cela se produit en arrière-plan et s'affiche chaque fois que vous êtes prêt (cela ne bloque peut-être pas l'interface utilisateur, mais c'est sûr que cela clignote ...)


Pourquoi la pré-création de formulaires en arrière-plan pendant les périodes d'inactivité serait-elle une mauvaise conception? (pour un temps de réponse encore légèrement plus rapide lors de son utilisation)


Pour être clair: je ne parle pas de charger le formulaire principal en arrière-plan (mais toutes sortes d'autres formulaires de support)


@DDeberla Pourquoi ne créez-vous pas ces formulaires de support sur demmand à la place juste après le démarrage de l'application. Créer des formulaires avant qu'ils ne soient nécessaires ne fait que gaspiller de la mémoire.


Je serais surpris si le chargement de la page Web pouvait être déchargé sur un fil séparé. Mais si c'est ce que vous voulez faire, posez des questions à ce sujet. Il semble que vous ayez posé une question sur la création de contrôles et de formulaires, mais en fait, vous souhaitez décharger autre chose. A savoir le chargement de la page.


J'apprécie tous les commentaires, mais la question est bien ce que je voulais savoir. J'ai donné 1 exemple, mais cela ne signifie pas que l'exemple remplace la question. Je vérifie quelles sont les limites de l'optimisation des temps de chargement des formulaires lorsque je m'en tiens à Delphi. @SilverWarior: Si les avantages (affichage instantané si nécessaire) surpassent les pénalités (consommation de mémoire), cela dépend vraiment de l'application. Mais vous avez raison, généralement pas. Mais cette fois, je ne suis pas habituel :-)


Je suppose qu'avec les réponses données, la réponse est: non, ce n'est pas possible.


Eh bien, je suppose que je me demandais si vous vouliez savoir quelque chose d'utile, ou s'il ne s'agissait que d'une question académique. Parce que la création de contrôles n'est pas votre goulot d'étranglement. Eh bien, je pense que oui. Avez-vous fait un benchmark pour me prouver le contraire?


Quelques lectures connexes . Ni VCL ni FMX ne sont thread-safe.


Merci à tous pour vos commentaires utiles, en particulier avec quelques informations sur le «pourquoi». Donc la réponse est non' .


3 Réponses :


-1
votes

J'ai trouvé que ce qui suit ne gèle pas instantanément, mais si c'est de la pure chance pour le moment ou de la sagesse, je ne suis pas sûr.
Au lieu de cela, si vous rendez le formulaire visible dans la partie de synchronisation du thread d'arrière-plan, je le fais `` vraiment '' dans le thread principal ...

(Je pourrais comprendre que tant que vous ne donnez aucun parent aux contrôles de l'interface utilisateur, ils sont «sûrs». Comment le thread principal connaîtrait-il leur existence?)

Je pourrais tester cela un peu plus après tout.

procedure TTabbedForm.Button1Click(Sender: TObject);
begin


 TThread.CreateAnonymousThread( procedure begin
    lForm := TForm1.Create(Self);

    TThread.Synchronize(nil,
     procedure begin
       //lForm.Parent := Self ;
       //lForm.Show ;
       Button2.Enabled := True ;
      end );

   end ).Start ;

end;

procedure TTabbedForm.Button2Click(Sender: TObject);
begin
 if Assigned(lForm) then begin
  lForm.Parent := Self ;
  lForm.Show ;
 end;

end;



2 commentaires

Non, ce n'est pas sûr même si vous ne lui donnez pas de parent ... cela peut être plus sûr car il échouera moins souvent, mais c'est du code cassé qui peut échouer de manière aléatoire.


"Comment le thread principal saurait-il ...?" De plus, comment connaîtraient-ils le thread principal? Je ne sais pas exactement ce que l'on entend par coffre-fort, mais si vous ne recevez pas d'exception immédiate, attendez-vous à ce qu'il y ait d'autres conséquences de cette configuration. F.i., sur les fenêtres au moins, l'énumération des fenêtres de thread exclura les fenêtres que vous souhaitez énumérer et vous devriez donc observer un échec comportemental des formulaires les plus élevés ou des formulaires modaux. Le framework suppose que c'est sur un seul thread, c'est aussi simple que ça.



3
votes

Je me demande s'il est possible de créer des éléments d'interface utilisateur, même complets formulaire, dans un thread d'arrière-plan ("sans l'utiliser bien sûr"), et une fois que c'est fait, rendez-le disponible dans le fil de discussion principal pour l'afficher.

NON.

La création et l'accès aux contrôles d'interface utilisateur à partir d'un thread d'arrière-plan ne sont pas sécurisés pour les threads.

Bien que vous puissiez créer un code de preuve de concept qui fonctionne apparemment, un tel code est intrinsèquement cassé. Il peut échouer au hasard.


0 commentaires

0
votes

Donc, en résumé, les contrôles d'interface utilisateur ne peuvent être utilisés en toute sécurité que dans le thread dans lequel ils sont créés, et vous ne pouvez pas changer ce comportement après leur création (et les rendre `` appartenant '' à un autre thread comme s'ils avaient été créés là en premier lieu).

Il se peut que conceptuellement, créer des formulaires qui n'interagissent pas avec un autre peut fonctionner en regardant
Comment créer un formulaire dans une DLL intégré à mon application?
Je suppose qu'ici aussi, le formulaire est en effet créé dans un fil différent, probablement même dans un processus différent, non?


1 commentaires

Les contrôles d'interface utilisateur doivent être créés et utilisés à partir du thread principal. Et ce message auquel vous avez lié ne dit rien sur l'interface utilisateur de thread croisé ou de processus croisé.