Revisité avec les Reactive Extensions: DataBinding et Mise à Jour depuis Plusieurs Threads

This article is available in english.

Récemment, j'ai écrit un article à propos des WinForms, DataBinding et Mises à Jour depuis plusieurs Threads, où j'expliquais comment externaliser l'exécution d'une méthode accrochée à un événement sur la thread de l'interface utilisateur.

J'ai utilisé alors une technique basée sur un Action<Action> qui prend avantage des "Closures", et le fait que l'action va transporter son contexte jusqu'à l'endroit où il doit être exécuté.

Ce concept d'externalisation peut être revisité avec les Reactive Extensions, et l'interface IScheduler.

L'exemple original

Voyons l'exemple de code original :

1
2
3
4
5
    public MyController(Action<Action> synchronousInvoker)
{
_synchronousInvoker = synchronousInvoker;
...
}

Ce code est le constructeur du contrôleur du formulaire, et l'action "synchronousInvoker" va être définie comme ceci :

1
    _controller = new MyController(a => Invoke(a));

Et utilisée comme ceci :

1
2
3
    _synchronousInvoker(
() => PropertyChanged(this, new PropertyChangedEventArgs("Status"))
);

Ou "Invoke" est en fait Control.Invoke(), utilisé pour exécuter du code sur la Thread de l'interface graphique, la où les mise à jour de contrôles graphiques peuvent être effectuées sans problèmes.

Bien que la technique Action<Action> fonctionne très bien pour parvenir à isoler les rôles, il n'est pas très évident, juste en regardant le constructeur, de savoir ce que l'on doit donner à ce fameux paramètre.

Utiliser l'interface IScheduler

Pour parvenir à isoler l'exécution du contenu des opérateurs du Reactive Framework, l'équipe du Rx a introduit le concept de Scheduler, avec un tas d'implémentations de schedulers communs.

Cela permet d'exposer simplement un moyen de planifier l'exécution d'une méthode dans le contexte qui est n'est pas à la charge de l'utilisateur. Bien souvent, le code qui utilise le scheduler ne veut pas s'occuper du contexte dans lequel est exécute le code. Dans notre cas, on veut exécuter notre code sur la pompe à message des WinForms, et ça tombe bien, "il y a un Scheduler pour ca".

L'exemple précédent peut être facilement mis à jour en utilisant IScheduler à la place de Action<Action>, et d'utiliser la méthode IScheduler.Schedule().

1
2
3
4
5
    public MyController(ISheduler scheduler)
{
_scheduler = scheduler;
...
}

Et de remplacer l'appel par :

1
2
3
    _scheduler.Schedule(
() => PropertyChanged(this, new PropertyChangedEventArgs("Status"))
);

Ce n'est pas une modification très complexe, mais cela le code bien plus compréhensible.

On peut utiliser le Scheduler fourni pour les WinForms, le non-documenté System.Concurrency.ControlScheduler (qui n'est pas présent dans la classe Scheduler parce qu'il ne peut pas être créé statiquement car il requiert une instance de Control) :

1
    _controller = new MyController(new ControlScheduler(this));

Avec "this" qui est une instance de Control.

Au final, le code est plus lisible, et pour ce qui est de faire des tests unitaires sur le Contrôleur, c'est tout à fait faisable avec le System.Concurrency.CurrentThreadScheduler, puisqu'il n'y a pas besoin de changer de threads dans les tests.


Que se passe-t-il avec les Reactive Extensions et Silverlight pour Windows Phone 7 ?

Dans un refactoring très étrange, l'équipe du WP7 a déplacé le IScheduler depuis System.Concurrency vers le très spécifique namespace Microsoft.Phone.Reactive.

Je ne comprend pas vraiment la raison d'un tel changement, et cela a le désagréable effet de rendre incompatible du code qui compilait facilement sur plusieurs plateformes.

Ils ont peut-être considéré que l'implémentation des Reactive Extensions pour Windows Phone était trop différente de la version Desktop... Mais le Compact Framework a été construit sur cette assomption, et la plupart du code est resté dans les même namespaces.

Si quelqu'un a une explication pour ce refactoring étrange, je suis tout ouïe :)

Publié lundi 26 juillet 2010 22:31 par jay
Classé sous , , , ,
Ce post vous a plu ? Ajoutez le dans vos favoris pour ne pas perdre de temps à le retrouver le jour où vous en aurez besoin :

Commentaires


Les 10 derniers blogs postés

- Office 365: Script PowerShell pour auditer l’usage des Office Groups de votre tenant par Blog Technique de Romelard Fabrice le 04-26-2019, 11:02

- Office 365: Script PowerShell pour auditer l’usage de Microsoft Teams de votre tenant par Blog Technique de Romelard Fabrice le 04-26-2019, 10:39

- Office 365: Script PowerShell pour auditer l’usage de OneDrive for Business de votre tenant par Blog Technique de Romelard Fabrice le 04-25-2019, 15:13

- Office 365: Script PowerShell pour auditer l’usage de SharePoint Online de votre tenant par Blog Technique de Romelard Fabrice le 02-27-2019, 13:39

- Office 365: Script PowerShell pour auditer l’usage d’Exchange Online de votre tenant par Blog Technique de Romelard Fabrice le 02-25-2019, 15:07

- Office 365: Script PowerShell pour auditer le contenu de son Office 365 Stream Portal par Blog Technique de Romelard Fabrice le 02-21-2019, 17:56

- Office 365: Script PowerShell pour auditer le contenu de son Office 365 Video Portal par Blog Technique de Romelard Fabrice le 02-18-2019, 18:56

- Office 365: Script PowerShell pour extraire les Audit Log basés sur des filtres fournis par Blog Technique de Romelard Fabrice le 01-28-2019, 16:13

- SharePoint Online: Script PowerShell pour désactiver l’Option IRM des sites SPO non autorisés par Blog Technique de Romelard Fabrice le 12-14-2018, 13:01

- SharePoint Online: Script PowerShell pour supprimer une colonne dans tous les sites d’une collection par Blog Technique de Romelard Fabrice le 11-27-2018, 18:01