Alors là, grosse déception ! La session était animée par Vincent Lainé, plus connu sous le pseudonyme de dev01 sur nos forums et membre de la rubrique .NET.. Mais rassure-toi Vincent, je n’ai pas été déçu par ta présentation (:p). La déception vient du fait que je voulais assister à la session sur l’extensibilité avec Visual Studio 2010 grâce à Microsoft Extensibility Framework (MEF) dont le titre dans le mail envoyé par Microsoft était « Visual Studio : comment l’adapter à vos besoins » (déjà avec un titre pareil, je ne me rappelais pas que c’était en rapport avec MEF) et dans le listing des sessions avec salles correspondantes, il était marqué « Extensibilité de Visual Studio ».

Ne sachant donc plus ce à quoi je voulais assister, j’ai pris la première session qui parlait de Visual Studio 2010 et qui était donc Visual Studio 2010 et TPL.

Cette session est consacrée au développement parallèle au travers de votre code managé dont trois fonctionnalités importantes furent abordées :

  1. PLinq
  2. Utilisation des tâches
  3. Les collections concurrentes (qui n’a pas été abordé pas manque de temps)

PLinq est en fait un provider Linq parallélisé afin d’exécuter des requêtes sur vos différents processeurs. Même si nous avons vu qu’il est très facile de réécrire une requête Linq simple en requête PLinq, Vincent a attiré notre attention sur quelques points et pièges à éviter.

Par rapport à une requête Linq, la version PLinq ne sera jamais autant de fois plus rapide qu’il y a de processeurs sur votre machine. Pour faire simple, une requête Linq, qui prend 2 secondes avec une machine munie de deux processeurs, ne s’exécutera pas deux fois plus vite en PLinq. La raison est que PLinq est beaucoup plus lourd car il entraine un certain nombre de synchronisation en différents threads qui sont générés. On pourra donc considérer qu’une requête PLinq sera 1,67 fois plus rapide plutôt que 2 fois.

Un piège à éviter est l’utilisation de ce genre de requêtes en Linq to SQL ou Linq to Entities :

<span style="color: #606060" id="lnum1">   1:</span> var query = from facture <span style="color: #0000ff">in</span> ctx.Factures.AsParallel()
<span style="color: #606060" id="lnum2">   2:</span>             select <span style="color: #0000ff">new</span> { factureID = facture.ID, ClientNom = facture.Client.Nom };

Une exception sera générée à l’exécution car cette requête est résolue en deux temps :

  • Récupération des données de la table Facture de manière parallèle
  • Génération des objets anonymes en retour des données chargées de la base de données

Sauf que seules les données de la table Facture ont été récupérées. Les données relatives au client ne le seront pas contrairement à ce que font les ORM Linq. Il va donc être nécessaire de modifier notre requête pour inclure les données de la table Client. Je n’ai pas d’exemple à vous montrer tellement la requête est devenue compliquée pour arriver au résultat espéré.

La seconde partie de la session est l’utilisation des tâches permettant de créer des threads plus facilement et de manière hiérarchique. Différentes classes sont mises à disposition :

  • Task : tout simplement notre tâche
  • TaskScheduler : le scheduler de tâches qui est une classe abstraite
  • TaskFactory : permettant de créer plus facilement un ensemble de tâches ayant le même scheduler, les mêmes options et aussi les mêmes systèmes d’annulation
  • CancellationTokenSource et CancellationToken : pour la gestion des annulations de tâches

Après une démo de mise à niveau d’une application écrite avec l’utilisation de threads classiques pour utiliser au final des tâches, une partie du sujet a été consacré au debugging avec la présentation de nouvelles fenêtres dans Visual Studio et qui permettent de visualiser les tâches parallèles, les piles d’appels, qui bloque qui, les états.

Il est aussi possible de collecter automatiquement un ensemble d’informations lors de l’exécution de votre application au travers de Visual Studio afin de générer un rapport et analyser de manière graphique sur une échelle de temps tout ce qui s’est déroulés au niveau des threads.