5

Je suis à la recherche d'un modèle de conception qui conviendrait à mon design d'application. Mon application traite de grandes quantités de données et produit quelques graphiques. Le traitement des données (récupération à partir des fichiers, calculs intensifs du processeur) et les opérations graphiques (dessin, mise à jour) sont effectués dans des threads séparés. Le graphique peut être défilé - dans ce cas, de nouvelles portions de données doivent être traitées. Étant donné qu'il peut y avoir plusieurs séries sur un graphique, plusieurs threads peuvent être générés (deux threads par série, un pour la mise à jour du jeu de données et un pour la mise à jour du graphique).barre de progression et plusieurs threads, découplage GUI et logique - quel modèle de conception serait le meilleur?

Je ne souhaite pas créer plusieurs barres de progression. Au lieu de cela, j'aimerais avoir une barre de progression unique qui informe sur les progrès mondiaux. En ce moment je peux penser à MVC et à Observer/Observable, mais c'est un peu flou :) Peut-être que quelqu'un pourrait me diriger dans la bonne direction, merci.

Répondre

1

Plusieurs barres de progression ne sont pas une si mauvaise idée, pensez-y. Ou peut-être une barre de progression complexe qui montre plusieurs threads en cours d'exécution (comme les programmes de gestionnaire de téléchargement ont parfois). Tant que l'interface utilisateur est intuitive, vos utilisateurs apprécieront les données supplémentaires.

Lorsque j'essaie de répondre à de telles questions de conception, j'essaie d'abord d'examiner des problèmes similaires ou analogues dans d'autres applications, et comment ils sont résolus. Je vous suggère donc de faire quelques recherches en considérant d'autres applications qui affichent des progrès complexes (comme l'exemple du gestionnaire de téléchargement) et d'essayer d'adapter une solution existante à votre application.

Désolé je ne peux pas offrir un design plus spécifique, ce n'est qu'un conseil général. :)

1

Stick avec observateur/observable pour ce genre de chose. Certains objets observent les différents threads de traitement en série et signalent l'état en mettant à jour la barre de résumé.

6

Une fois, j'ai passé une bonne partie de la semaine à essayer de faire une barre de progression lisse et non-hiccupy sur un algorithme très complexe.

L'algorithme avait 6 étapes différentes. Chaque étape avait des caractéristiques temporelles qui dépendaient sérieusement de A) les données sous-jacentes traitées, non seulement la "quantité" de données mais aussi le "type" de données et B) 2 des étapes mises à l'échelle extrêmement bien avec un nombre croissant de cpus, 2 étapes ont couru dans 2 discussions et 2 étapes ont été effectivement mono-thread.

Le mélange de données a effectivement eu un impact beaucoup plus important sur le temps d'exécution de chaque étape que le nombre de cœurs.

La solution qui a finalement craqué était vraiment très simple. J'ai fait 6 fonctions qui ont analysé l'ensemble de données et essayé de prédire l'exécution réelle de chaque étape d'analyse. L'heuristique dans chaque fonction analysait à la fois les ensembles de données analysés et le nombre de cpus. Basé sur les données d'exécution de mon propre ordinateur 4 core, chaque fonction a fondamentalement renvoyé le nombre de millisecondes qu'il était prévu de prendre, sur ma machine.

f1 (..) + f2 (..) + f3 (..) + f4 (..) + f5 (..) + f6 (..) = durée totale en millisecondes

maintenant donné cette information, vous pouvez effectivement savoir quel pourcentage du temps total d'exécution chaque étape est censée prendre. Maintenant, si vous dites que l'étape 1 est censée prendre 40% du temps d'exécution, vous devez essentiellement savoir comment émettre 40 événements 1% à partir de cet algorithme.Dites la boucle for est en train de traiter 100.000 articles, vous pourriez probablement faire:

for (int i = 0; i < numItems; i++){ 
    if (i % (numItems/percentageOfTotalForThisStep) == 0) emitProgressEvent(); 
    .. do the actual processing .. 
} 

Cet algorithme nous a donné une barre de progression douce et soyeuse qui a fonctionné parfaitement. Votre technologie d'implémentation peut avoir différentes formes de mise à l'échelle et de fonctionnalités disponibles dans la barre de progression, mais la façon de penser de base du problème est la même.

Et oui, cela n'a pas vraiment d'importance que les numéros de référence heuristiques aient été élaborés sur ma machine - le seul vrai problème est si vous voulez changer les numéros en cours d'exécution sur une machine différente. Mais vous connaissez toujours le ratio (qui est la seule chose vraiment importante ici), donc vous pouvez voir comment votre matériel local fonctionne différemment de celui que j'avais.

Maintenant, le lecteur moyen de SO peut se demander pourquoi quelqu'un aurait passé une semaine à faire une barre de progression en douceur. La fonctionnalité a été demandée par le vendeur en chef, et je crois qu'il l'a utilisé dans les réunions de vente pour obtenir des contrats. Money talks;)

+1

Renversé pour la fraîcheur. – erikprice

2

Dans les situations avec des threads ou des processus/tâches asynchrones comme celui-ci, je trouve utile d'avoir un type abstrait ou un objet dans le thread principal qui représente (et idéalement encapsule) chaque processus. Ainsi, pour chaque thread de travail, il y aura vraisemblablement un objet (appelons-le Operation) dans le thread principal pour gérer ce worker, et évidemment il y aura une sorte de structure de données semblable à une liste pour contenir ces opérations. Le cas échéant, chaque opération fournit les méthodes de démarrage/arrêt pour son opérateur, et dans certains cas, comme par exemple les vôtres, les propriétés numériques représentant la progression et le temps total prévu ou le travail de la tâche de cette opération particulière. Les unités n'ont pas nécessairement besoin d'être basées sur le temps, si vous savez que vous effectuerez 6 230 calculs, vous pouvez simplement considérer ces propriétés comme des calculs. En outre, chaque tâche devra avoir un moyen de mettre à jour son propre fonctionnement de sa progression actuelle, quel que soit le mécanisme approprié (rappels, fermetures, répartition d'événements ou tout autre mécanisme fourni par votre langage de programmation/framework de threading).

Ainsi, pendant que votre travail actuel est effectué dans des threads séparés, un objet Operation correspondant dans le thread "principal" est continuellement mis à jour/informé de la progression de son worker. La barre de progression peut se mettre à jour en conséquence, en faisant correspondre le total des temps "attendus" des Opérations à son total et le total des "progrès" des Opérations à sa progression actuelle, de quelque manière que ce soit. De toute évidence, il y a beaucoup d'autres considérations/travaux qui doivent être faits pour l'implémenter réellement, mais j'espère que cela vous donnera une idée générale.

Questions connexes