Concepts avancés
Asynchronisme
1. Fonctionnement de base
Avant d’aborder l’asynchronisme en détail, il est nécessaire de mettre en place un peu de terminologie, notamment afin de bien comprendre deux notions qui sont distinctes mais souvent confondues : le parallélisme et l’asynchronisme.
Cette section va aborder le concept d’asynchronisme, qui consiste à déléguer une opération en arrière-plan et continuer d’exécuter le code restant lorsque l’opération est terminée. Afin de bien comprendre la logique derrière l’asynchronisme, nous pouvons tenter une comparaison avec un exemple de la vie courante.
Lorsque que nous lançons une machine pour laver notre linge, celle-ci effectue son travail de façon asynchrone par rapport à nous-mêmes, ce qui permet, pendant ce temps, de nous occuper à faire autre chose. Quand elle a fini son cycle, elle émet un son pour prévenir, et nous pouvons dès lors récupérer le linge pour aller l’étendre. En considérant que nous sommes le programme principal et que le linge est le code devant être exécuté de façon asynchrone, nous pouvons voir la notion d’asynchronisme.
Dès lors que nous mettons le linge dans la machine et que nous la lançons, nous déléguons du travail appliqué à ce linge à une autre entité que nous-mêmes. Pendant ce travail, nous pouvons reprendre notre propre travail. Lorsque le lavage est terminé, la machine va émettre un signal sonore afin que nous sortions le linge de la machine pour l’étendre. C’est là le concept d’asynchronisme : la machine a travaillé en asynchrone par rapport à nous.
Quant au parallélisme, il s’agit d’effectuer plusieurs choses en même temps. Par exemple, si nous choisissons de lancer une machine à laver et que, dans le même intervalle, nous lançons également le lave-vaisselle, les deux machines vont tourner en parallèle en consommant des ressources partagées (eau, électricité). Cela permet d’optimiser le temps d’exécution tout en partageant les mêmes ressources.
Les deux notions, bien que complémentaires, ne doivent...
Algorithmique avancée
Tout au long de l’ouvrage, nous avons étudié l’algorithmique de base, qui permet de couvrir un large périmètre fonctionnel. Néanmoins, C# et le framework .NET possèdent énormément de fonctionnalités plus avancées. Nous allons en étudier certaines dans ce chapitre.
1. Programmation événementielle
La programmation événementielle permet de réagir à des événements qui surviennent durant l’exécution d’une application. Jusqu’à présent, nous avons réagi de façon synchrone à un événement particulier (comme, par exemple, attendre que l’utilisateur saisisse une valeur dans la console). Cependant, C# offre un mécanisme puissant qui permet de faire de la programmation réactive, c’est-à-dire de ne pas attendre un quelconque événement mais de réagir uniquement quand ce dernier s’est produit.
a. Les delegates
Pour bien appréhender le sujet, il est nécessaire de comprendre un principe qui remonte à C# 2 : les delegates. Un delegate est l’équivalent d’un descripteur d’une méthode, et une variable de type delegate correspond à un pointeur effectif vers une méthode.
Pour déclarer un delegate, il faut utiliser le mot-clé dédié, delegate, puis déclarer la signature de méthode que nous souhaitons représenter, avec son type de retour et ses éventuels paramètres (ou parenthèses vides s’il n’y a aucun paramètre) :
public delegate void MonDelegueVoidSansParametres();
public delegate string MonDelegueRetourneString();
public delegate void MonDelegueVoidAvecParametres(string data);
Dans le bloc de code ci-dessus, nous avons déclaré trois delegates :
-
Le premier permet de représenter une méthode qui retourne void et ne prend pas de paramètres.
-
Le second permet de représenter une méthode qui retourne un string et ne prend pas de paramètres.
-
Le troisième permet de représenter une méthode qui retourne void et prend un paramètre de type string.
Les delegates peuvent être déclarés...