J'ai lu un certain nombre de documents techniques, rédigés par l'équipe de Microsoft ou par d'autres auteurs, qui détaillent les fonctionnalités de la nouvelle bibliothèque TPL Dataflow, des cadres de concurrence async/await et de TPL. Cependant, je n'ai pas vraiment trouvé de document qui définisse clairement lequel utiliser et quand. Je suis conscient que chacun a sa place et son applicabilité, mais je m'interroge plus particulièrement sur la situation suivante :
J'ai un modèle de flux de données qui fonctionne entièrement en cours de processus. Au sommet se trouve un composant de génération de données (A) qui génère des données et les transmet à un composant de traitement (B) soit par des liens de blocs de flux de données, soit par des événements d'augmentation. Certaines parties de (B) doivent s'exécuter de manière synchrone, tandis que (A) bénéficie massivement du parallélisme, car la plupart des processus sont liés aux E/S ou au CPU (lecture de données binaires sur le disque, puis désérialisation et tri). Enfin, le composant de traitement (B) transmet les résultats transformés à (C) pour une utilisation ultérieure.
Je me demande spécifiquement quand utiliser les tâches, async/await et les blocs de flux de données TPL dans les cas suivants :
-
Lancement de la composante de génération de données (A). Il est clair que je ne veux pas verrouiller le gui/dashboard, donc ce processus devrait être exécuté sur un autre thread/tâche.
-
Comment appeler des méthodes dans (A), (B) et (C) qui ne sont pas directement impliquées dans le processus de génération et de traitement des données, mais qui effectuent un travail de configuration dont le retour peut prendre plusieurs centaines de millisecondes/secondes. J'ai l'impression que c'est là qu'async/await fait merveille ?
-
Ce qui me pose le plus de problèmes, c'est la manière de concevoir au mieux le passage des messages d'un composant à l'autre. TPL Dataflow semble très intéressant mais il est parfois trop lent pour mes besoins. (Note à la fin concernant les problèmes de performance). Si je n'utilise pas TPL Dataflow, comment puis-je obtenir la réactivité et la concurrence par le passage de données inter-tâches/concurrentes en cours de processus ? Par exemple, si je déclenche un événement dans une tâche, le gestionnaire d'événement souscrit s'exécute dans la même tâche au lieu d'être transmis à une autre tâche, n'est-ce pas ? En résumé, comment le composant (A) peut-il vaquer à ses occupations après avoir transmis des données au composant (B) pendant que ce dernier récupère les données et se concentre sur leur traitement ? Quel est le meilleur modèle de concurrence à utiliser ici ? J'ai implémenté des blocs de flux de données ici, mais est-ce vraiment la meilleure approche ?
-
Je pense que les points ci-dessus résument ma difficulté à concevoir et à mettre en œuvre des composants de type API en utilisant des pratiques standard ? Les méthodes doivent-elles être conçues de manière asynchrone, les entrées de données sous forme de blocs de flux de données et les sorties de données sous forme de blocs de flux de données ou d'événements ? Quelle est la meilleure approche en général ? Je pose la question parce que la plupart des composants mentionnés ci-dessus sont censés fonctionner indépendamment, de sorte qu'ils peuvent essentiellement être remplacés ou modifiés indépendamment en interne sans avoir à réécrire les accesseurs et la sortie.
Note sur la performance : J'ai mentionné que les blocs TPL Dataflow sont parfois lents. Je m'occupe d'un type d'application à haut débit et faible latence et je vise des limites d'E/S de disque et donc les blocs de flux de données TPL fonctionnent souvent beaucoup plus lentement que, par exemple, une unité de traitement synchrone. Le problème est que je ne sais pas comment intégrer le processus dans sa propre tâche ou modèle concurrent pour obtenir quelque chose de similaire à ce que les blocs tpl dataflow font déjà, mais sans la surcharge qui vient avec tpl df.