IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

  1. #1
    Futur Membre du Club
    Homme Profil pro
    Développeur informatique
    Inscrit en
    février 2021
    Messages
    5
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Pays-Bas

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : février 2021
    Messages : 5
    Points : 5
    Points
    5
    Par défaut [FMX][Android] Détecter la fin d'un thread secondaire dans le thread principal
    Bonjour,

    Dans une app Android, j'ai une requête à une base de données qui prend de 5 à 10 secondes pour récupérer les informations demandées.

    Je désire donc ajouter à l'app un fonctionnement du style:

    1. J'affiche un écran "chargement en cours..."
    2. Je fais la requête
    3. A la fin de la requête, j'efface l'écran "chargement en cours..."


    Aucun problème sur windows, mais je n'arrive pas à avoir ce fonctionnement sur Android: Impossible d'effacer l'écran. Je pense que la ligne de code qui efface l'écran s'exécute avant la fin de la requête et donc au final l'app reste bloquée sur l'écran "chargement en cours...".

    J'ai essayé avec un thread du style:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    procedure TForm1.GetDataFromServer;
    begin
     Tthread.CreateAnonymousThread(
      procedure
       begin
        TabControl1.ActiveTab:=tabLoading; //Affichage de l'écran "Chargement en cours"
     
        {Appel à la procédure qui effectue la requête et traite les données reçues};
     
        Tthread.Synchronize(TThread.CurrentThread,
         procedure
          begin
           TabControl1.ActiveTab:=tabSynchro; //Suppression de l'écran "Chargement en cours" par l'appel d'un autre écran
          end);
     
       end).Start;
    Ce code fonctionne avec windows mais pas avec Android.

    Je ne suis pas un grand spécialiste des Thread. Est-ce que je peux détecter en dehors du Thread (après le code ".start;") la fin du Thread pour placer ma commande "TabControl1.ActiveTab:=tabSynchro;"? Si oui, comment?

    Est-ce qu'il y a une autre solution?

    Merci de votre aide

  2. #2
    Membre chevronné Avatar de pprem
    Homme Profil pro
    MVP Embarcadero - développeur Delphi, PHP et JS
    Inscrit en
    juin 2013
    Messages
    823
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loiret (Centre)

    Informations professionnelles :
    Activité : MVP Embarcadero - développeur Delphi, PHP et JS
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : juin 2013
    Messages : 823
    Points : 1 802
    Points
    1 802
    Par défaut
    Attention : tout accès à l'interface utilisateur depuis un thread doit être synchronisé avec le thread principal.

    Tu le fais bien pour la réactivation de l'écran de base, il faut aussi le faire lorsque tu affiches l'autre.

  3. #3
    Futur Membre du Club
    Homme Profil pro
    Développeur informatique
    Inscrit en
    février 2021
    Messages
    5
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Pays-Bas

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : février 2021
    Messages : 5
    Points : 5
    Points
    5
    Par défaut
    Citation Envoyé par pprem Voir le message
    Attention : tout accès à l'interface utilisateur depuis un thread doit être synchronisé avec le thread principal.

    Tu le fais bien pour la réactivation de l'écran de base, il faut aussi le faire lorsque tu affiches l'autre.
    J'ai aussi testé le code avec le premier écran synchronisé. Que le premier écran soit synchronisé ou pas, il apparait normalement.

    C'est l'écran qui suit la requête longue qui n'apparait pas malgré le fait qu'il soit synchronisé!!!

  4. #4
    Membre chevronné Avatar de pprem
    Homme Profil pro
    MVP Embarcadero - développeur Delphi, PHP et JS
    Inscrit en
    juin 2013
    Messages
    823
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loiret (Centre)

    Informations professionnelles :
    Activité : MVP Embarcadero - développeur Delphi, PHP et JS
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : juin 2013
    Messages : 823
    Points : 1 802
    Points
    1 802
    Par défaut
    ça devrait passer, mais par mesure de prudence peut-être devrais-tu écrire un truc comme ça ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    procedure TForm1.GetDataFromServer;
    begin
     Tthread.CreateAnonymousThread(
      procedure
       begin
        Tthread.Synchronize(TThread.CurrentThread,
         procedure
          begin
        TabControl1.ActiveTab:=tabLoading; //Affichage de l'écran "Chargement en cours"
    end);
    try 
        {Appel à la procédure qui effectue la requête et traite les données reçues};
     finally
        Tthread.Synchronize(TThread.CurrentThread,
         procedure
          begin
           TabControl1.ActiveTab:=tabSynchro; //Suppression de l'écran "Chargement en cours" par l'appel d'un autre écran
          end);
     end;
       end).Start;

  5. #5
    Expert éminent sénior
    Avatar de Paul TOTH
    Homme Profil pro
    Freelance
    Inscrit en
    novembre 2002
    Messages
    7 915
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Freelance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : novembre 2002
    Messages : 7 915
    Points : 25 692
    Points
    25 692
    Par défaut
    euh à priori je ferais simplement

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
     
    procedure TForm1.GetDataFromServer;
    begin
      TabControl1.ActiveTab:=tabLoading; //Affichage de l'écran "Chargement en cours"
     
      Tthread.CreateAnonymousThread(
      procedure
       begin
     
        {Appel à la procédure qui effectue la requête et traite les données reçues}; 
         ...
     
        Tthread.Synchronize(TThread.CurrentThread,
         procedure
          begin
           TabControl1.ActiveTab:=tabSynchro; //Suppression de l'écran "Chargement en cours" par l'appel d'un autre écran
          end);
     
       end).Start;
    end;
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

  6. #6
    Membre expert

    Homme Profil pro
    Développeur informatique
    Inscrit en
    novembre 2006
    Messages
    578
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Deux Sèvres (Poitou Charente)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Finance

    Informations forums :
    Inscription : novembre 2006
    Messages : 578
    Points : 3 129
    Points
    3 129
    Billets dans le blog
    2
    Par défaut
    Bonjour,

    Je me permets d'ajouter une autre possibilité :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    procedure TForm1.GetDataFromServer;
    begin
      TTask.Create( procedure
        begin
          TabControl1.ActiveTab:=tabLoading; //Affichage de l'écran "Chargement en cours"
          [... Traitement long...]
          TabControl1.ActiveTab:=tabSynchro; //Suppression de l'écran "Chargement en cours" par l'appel d'un autre écran
        end
      ).start
    end;
    Mon site - Mes tutoriels - GitHub - N'oubliez pas de consulter les FAQ Delphi et les cours et tutoriels Delphi

  7. #7
    Rédacteur/Modérateur
    Avatar de Andnotor
    Profil pro
    Inscrit en
    septembre 2008
    Messages
    5 062
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : septembre 2008
    Messages : 5 062
    Points : 11 058
    Points
    11 058
    Par défaut
    Citation Envoyé par vinkelwin Voir le message
    Est-ce que je peux détecter en dehors du Thread (après le code ".start;") la fin du Thread pour placer ma commande "TabControl1.ActiveTab:=tabSynchro;"? Si oui, comment?
    Bien sûr. CreateAnonymousThread crée une instance TThread. Tu peux dès lors lui associer un événement OnTerminate.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    TThread.CreateAnonymousThread(procedure
                                  begin
                                    TThread.Current.OnTerminate := MyThreadTerminated;
                                    ...
                                  end).Start;

  8. #8
    Futur Membre du Club
    Homme Profil pro
    Développeur informatique
    Inscrit en
    février 2021
    Messages
    5
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Pays-Bas

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : février 2021
    Messages : 5
    Points : 5
    Points
    5
    Par défaut
    Un grand remerciement à tous pour votre aide.

    La solution de pprem avec le "try...finally" (tellement simple que je n'y ai pas pensé ) fonctionne parfaitement.

    La solution de Toth: Oui il est logique de mettre "TabControl1.ActiveTab:=tabLoading;" en dehors du thread par contre la synchronisation dans le thread ne permet pas d'afficher l'écran après la procédure longue.

    Idem pour la solution de gbegreg, l'écran après la procédure longue n'apparait pas.

    Merci à Andnotor pour la réponse à ma question initiale. Je ne vais pas utiliser cette approche içi, mais ta réponse me sera très utile dans d'autre cas.

    Au final, la solution prend la forme suivante:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
     
    procedure TForm1.GetDataFromServer;
    begin
     
     TabControl1.ActiveTab:=tabLoading; //Affichage de l'écran "Chargement en cours"
     
     Tthread.CreateAnonymousThread(
      procedure
       begin
        try
         {Appel à la procédure qui effectue la requête et traite les données reçues};
          ... 
        finally
         Tthread.Synchronize(TThread.CurrentThread,
          procedure
           begin
            TabControl1.ActiveTab:=tabSynchro; //Suppression de l'écran "Chargement en cours" par l'appel d'un autre écran
           end);
        end;
     
     end).Start;
     
    end;

  9. #9
    Membre chevronné Avatar de pprem
    Homme Profil pro
    MVP Embarcadero - développeur Delphi, PHP et JS
    Inscrit en
    juin 2013
    Messages
    823
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loiret (Centre)

    Informations professionnelles :
    Activité : MVP Embarcadero - développeur Delphi, PHP et JS
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : juin 2013
    Messages : 823
    Points : 1 802
    Points
    1 802
    Par défaut
    Par contre, si ma solution fonctionne, ça veut dire que ton code génère une exception. Pense à vérifier ce qu'il en est en.

  10. #10
    Membre chevronné Avatar de pprem
    Homme Profil pro
    MVP Embarcadero - développeur Delphi, PHP et JS
    Inscrit en
    juin 2013
    Messages
    823
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loiret (Centre)

    Informations professionnelles :
    Activité : MVP Embarcadero - développeur Delphi, PHP et JS
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : juin 2013
    Messages : 823
    Points : 1 802
    Points
    1 802
    Par défaut
    Citation Envoyé par gbegreg Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
      TTask.Create( procedure
        begin
          TabControl1.ActiveTab:=tabLoading; //Affichage de l'écran "Chargement en cours"
          [... Traitement long...]
          TabControl1.ActiveTab:=tabSynchro; //Suppression de l'écran "Chargement en cours" par l'appel d'un autre écran
        end
      ).start
    dans ce cas peut-être plutôt TTask.run(), ça évite d'oublier le .start (ce que je loupe assez régulièrement)

  11. #11
    Rédacteur/Modérateur
    Avatar de Andnotor
    Profil pro
    Inscrit en
    septembre 2008
    Messages
    5 062
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : septembre 2008
    Messages : 5 062
    Points : 11 058
    Points
    11 058
    Par défaut
    Attention tout de même : TTask ne dispense pas d'une synchronisation avec le thread principal. La proposition de gbegreg n'est pas thread-safe.

  12. #12
    Membre expert

    Homme Profil pro
    Développeur informatique
    Inscrit en
    novembre 2006
    Messages
    578
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Deux Sèvres (Poitou Charente)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Finance

    Informations forums :
    Inscription : novembre 2006
    Messages : 578
    Points : 3 129
    Points
    3 129
    Billets dans le blog
    2
    Par défaut
    Oui tout à fait Andnotor, je suis allé un peu vite.
    On peut rajouter la synchronisation comme dans l'exemple de Paul. C'était juste une autre possibilité (mais très similaire) que celle du CreateAnonymousThread.
    Mon site - Mes tutoriels - GitHub - N'oubliez pas de consulter les FAQ Delphi et les cours et tutoriels Delphi

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Thread FMX Android plante
    Par retwas dans le forum Composants FMX
    Réponses: 17
    Dernier message: 03/12/2013, 09h30
  2. [Servlet] Comment détecter la fin d'une session HTTP
    Par cocula dans le forum Servlets/JSP
    Réponses: 2
    Dernier message: 18/04/2005, 18h27
  3. [Réseau] détecter la fin de lecture dans un flux entrant
    Par al85 dans le forum Entrée/Sortie
    Réponses: 5
    Dernier message: 30/03/2005, 22h06
  4. [TMediaPlayer] Détecter la fin de lecture
    Par ysr1 dans le forum C++Builder
    Réponses: 1
    Dernier message: 30/09/2004, 19h03
  5. [MFC]Détection de la fin d'un thread
    Par Oberown dans le forum MFC
    Réponses: 17
    Dernier message: 25/08/2004, 12h51

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo