Je dirais que TPL Dataflow couvre un sous-ensemble spécialisé de fonctionnalités dans Rx. Le flux de données est destiné au traitement de données qui peut prendre un temps mesurable, tandis que Rx concerne les événements, tels que la position de la souris, les états d'erreur, etc., où le temps de traitement est négligeable. Exemple: votre gestionnaire "subscribe" est asynchrone et vous ne voulez pas plus d'un exécuteur à la fois. Avec Rx vous devez bloquer, il n'y a pas d'autre moyen de contourner cela, parce que Rx est indépendant de l'async et ne menace pas async d'une manière spéciale dans de nombreux endroits.
.Subscribe(myAsyncHandler().Result)
Si vous ne bloquez pas, alors Rx considérera que l'action est terminée tout gestionnaire est toujours en cours d'exécution en mode asynchrone.
Vous pourriez penser que si vous faites
.ObserveOn(Scheduler.EventLoopSchedule)
que problème est résolu. Mais cela va casser votre flux de travail .Complete(), parce que Rx pensera que c'est fait dès qu'il planifie l'exécution et vous quitterez votre application sans attendre la fin de l'opération asynchrone.
Si vous ne voulez pas autoriser plus de 4 tâches asynchrones simultanées, Rx n'offre rien de prêt à l'emploi. Vous pouvez peut-être pirater quelque chose en implémentant votre propre planificateur, tampon, etc.
TPL Dataflow offre une très belle solution dans ActionBlock.Il peut limiter les actions simultanées à un certain nombre et il comprend les opérations asynchrones, ainsi l'appel de Complete() et l'attente de Completed feront exactement ce à quoi vous vous attendez: attendre que toutes les tâches asynchrones en cours se terminent.
Une autre caractéristique de TPL est la "contre-pression". Disons que vous avez découvert une erreur dans votre routine de traitement et devez recalculer les données du mois dernier. Si vous vous abonnez à votre source en utilisant Rx, et que votre pipeline contient des tampons illimités, ou ObserveOn, vous manquerez de mémoire en l'espace de quelques secondes car la source continuera à lire plus vite que le traitement ne peut en traiter. Même si vous implémentez le blocage du consommateur, votre source peut souffrir de bloquer les appels, par exemple si la source est asynchrone. En TPL vous pouvez mettre en œuvre comme source
while(...)
await actionBlock.SendAsync(msg)
qui ne bloque encore la source ne sera pas attendre tout gestionnaire est surchargé. Dans l'ensemble, j'ai trouvé que Rx est bien adapté pour les actions qui sont le temps et la lumière de calcul. Si le temps de traitement devient important, vous êtes dans le monde des effets secondaires étranges et du débogage ésotérique.
Bonne nouvelle: les blocs TPL Dataflow jouent très bien avec Rx. Ils ont des adaptateurs AsObserver/AsObservable et vous pouvez les coller au milieu du pipeline Rx si nécessaire. Mais Rx a beaucoup plus de modèles et de cas d'utilisation. Donc, ma règle générale est de commencer avec Rx et d'ajouter TPL Dataflow si nécessaire.
lien vers une question plus ancienne, fermée, en double: http://stackoverflow.com/questions/2138361/reactive-framework-vs-plinq-vs-task-parallel-library-vs-parallel-extensions/2188259 – yzorg