Pour rendre l'expérience utilisateur agréable, une application ne doit jamais se faire attendre. L'utilisation de threads s'impose donc pour déporter les traitements les plus coûteux en temps.


Précaution fondamentale dans le domaine : la mise à jour de l'UI doit toujours se faire depuis le thread principal de l'application. Il s'agit d'un sujet déjà décrit, malgré cela les erreurs dans ce domaine restent courantes (cf. Traitements dans un thread secondaire ou avec des tâches parallèles, toujours utiliser le thread principal pour la mise à jour de l'UI...).


Si une application tente de mettre à jour l'UI depuis une traitement lancé dans un thread, le mécanisme de sécurité du WLangage sera déclenché :

L'accès aux champs est interdit dans ce thread.

Utilisez une procédure à exécution dans le thread principal pour manipuler les champs.

Code erreur : 2949

ou :

Controls cannot be accessed in this thread.
Use a main thread procedure to manage controls.

Error code : 2949

 

Pour compléter le billet précédent sur la mise à jour de l'UI, voici différentes syntaxes qui permettent l'exécution d'un code dans le thread principal, à partir d'un thread secondaire. Pour l'exemple, prenons une procédure exécutée dans un thread pour répondre aux appels de la fonction fSurveilleRépertoire, et qui doit se terminer par l'ajout d'un message "sMessage" dans une liste de la fenêtre (cf exemple standard WD ObservateurRépertoire et sa procédure _ModificationsRépertoire).


Solution 1 : créer une procédure interne dans la procédure du thread, avec un attribut d'extension :

pAjouteLog(sMessage)
PROCEDURE INTERNE pAjouteLog(psMessage) <thread principal>
Trace("Ajout avec procédure interne : "+psMessage)
ListeAjoute(LISTE_FICHIERS,psMessage)
FIN

 


Solution 2 : utiliser la fonction ExécuteThreadPrincipal, différentes variantes existent :

  • éviter la création d'une autre procédure interne ou locale avec une lambda :
    • qui contient le code :

      ExécuteThreadPrincipal(()=>{Trace("Ajout avec Lambda : "+sMessage);ListeAjoute(LISTE_FICHIERS,sMessage)})

    • ou dont le code vient d'une chaîne qui pourrait être construite dynamiquement :

      sCode est une chaîne = [
      trace("Ajout avec ExécuteCode : "+sMessage)
      ListeAjoute(LISTE_FICHIERS,sMessage)
      ]
      ExécuteThreadPrincipal(()=>{ExécuteCode(sCode)})

  • au contraire utiliser une procédure existante avec une variable de type procédure. La variable procédure peut être affectée par une procédure locale de la fenêtre, globale d'une collection, voir même d'une autre fenêtre en la passant en paramètre à la procédure du thread :

    ProcédureAffiche est une Procedure = AjouteLog
    ExécuteThreadPrincipal(()=>{ProcédureAffiche(sMessage)})

 

Solution 3 : utiliser le code de mise à jour de l'affichage de la fenêtre :

DemandeMiseAJourUI(sMessage)

Avec dans les traitements associés à la fenêtre :

 

< Retour

Publier un commentaire : 
Votre adresse email ne sera pas publiée