Le meilleur moyen de maintenir l’interface utilisateur à jour?

Cette question est un raffinement de ma question. Différentes façons d’observer les modifications de données .

J’ai encore beaucoup de classes dans mon application C ++, qui sont mises à jour (ou pourraient être mises à jour) fréquemment dans des routines mathématiques complexes et dans des éléments complexes de la logique métier.

Si je choisis l’approche «observateur» et envoie des notifications chaque fois qu’une valeur d’instance est modifiée, j’ai 2 gros risques:

  • l’envoi des notifications lui-même peut ralentir sérieusement les applications
  • si les éléments de l’interface utilisateur doivent être mis à jour à la suite des modifications, ils le sont à chaque modification, ce qui permet par exemple de mettre à jour des écrans plusieurs milliers de fois pendant l’exécution d’une partie de la logique métier.

Certains problèmes peuvent être résolus en ajoutant des mécanismes de mise en mémoire tampon (où vous envoyez des notifications lorsque vous allez commencer avec un algorithme et lorsque l’algorithme est terminé), mais puisque la logique métier peut être exécutée à de nombreux endroits du logiciel, nous finissent par append un tampon presque partout, après chaque action possible choisie dans le menu.

À la place de l’approche “observateur”, je pouvais également utiliser l’approche “mark-dirty”, en ne marquant que les instances modifiées, et en indiquant l’action à la fin de l’action à l’interface utilisateur de se mettre à jour.

Là encore, la logique applicative peut être exécutée à partir de n’importe où dans l’application. En pratique, il peut donc être nécessaire d’append un appel supplémentaire (indiquant à toutes les fenêtres qu’elles doivent se mettre à jour elles-mêmes) après presque chaque action exécutée par l’utilisateur.

Les deux approches semblent avoir des inconvénients similaires mais opposés:

  • Avec l’approche “observateur”, nous risquons de mettre à jour l’interface utilisateur trop souvent
  • Avec l’approche «mark-dirty», nous risquons de ne pas mettre à jour l’interface utilisateur du tout.

Les deux inconvénients pourraient être résolus en incorporant chaque action de l’application dans une logique supplémentaire (pour les observateurs: envoi de notifications de début à la fin, pour mark-dirty: envoi de notifications de mise à jour vous-même).

Notez que dans les applications autres que Windows, ce n’est probablement pas un problème. Vous pouvez par exemple utiliser l’approche mark-dirty et si certains calculs nécessitent des données, il peut être nécessaire d’effectuer un traitement supplémentaire au cas où les données sont sales (il s’agit d’une sorte d’approche de mise en cache).

Cependant, pour les applications de fenêtrage, rien n’indique que l’utilisateur “regarde votre écran” et que les fenêtres doivent être mises à jour. Il n’ya donc pas vraiment de bon moment où vous devez regarder les données sales (bien que vous puissiez faire quelques astuces avec des événements de focus).

Quelle est la bonne solution pour résoudre ce problème? Et comment avez-vous résolu de tels problèmes dans votre application?

Notez que je ne souhaite pas introduire de techniques de fenêtrage dans la partie calcul / modèle de données de mon application. Si des techniques de fenêtrage sont nécessaires pour résoudre ce problème, il ne doit être utilisé que dans la partie interface utilisateur de mon application.

Une idée?

Une approche que j’avais utilisée avec une grande application Windows il ya quelques années consistait à utiliser WM_KICKIDLE . Toutes les choses pouvant être IdleTarget jour utilisent une classe de base abstraite appelée IdleTarget . Un IdleTargetManager intercepte ensuite les messages KICKIDLE et appelle la mise à jour sur une liste de clients enregistrés. Dans votre cas, vous pouvez créer une liste de cibles spécifiques à mettre à jour mais j’ai trouvé la liste de clients enregistrés suffisante.

Le seul piège que j’ai touché était un graphique en temps réel. En utilisant uniquement le message kick idle, le processeur atteindrait 100% en raison de la mise à jour constante du graphique. Utilisez une timer pour dormir jusqu’à ce que le prochain rafraîchissement résolve ce problème.

Si vous avez besoin de plus d’assistance, je suis disponible à des tarifs raisonnables … 🙂

Un autre point auquel je pensais.

Si vous êtes submergé par le nombre d’événements générés et éventuellement par le travail supplémentaire que cela entraîne, vous pouvez adopter une approche en deux phases:

  • Faire le travail
  • Commettre

où les notifications ne sont envoyées que sur commit.

Cela a le désavantage de forcer à réécrire du code …

Vous pouvez utiliser le modèle d’observateur avec coalescence. Il serait peut-être un peu moche à implémenter en C ++, cependant. Cela ressemblerait à ceci:

 m_observerList.beginCoalescing(); m_observerList.notify(); m_observerList.notify(); m_observerList.notify(); m_observerList.endCoalescing(); //observers are notified here, only once 

Ainsi, même si vous appelez notify trois fois, les observateurs ne sont pas notifiés jusqu’à endCoalescing que endCoalescing soit averti une seule fois.