février
2010
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 :
- PLinq
- Utilisation des tâches
- 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 :
1: var query = from facture in ctx.Factures.AsParallel()
2: select new { 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.
5 Commentaires + Ajouter un commentaire
Déménagement
Next Microsoft CEO
Articles récents
- Changement d’adresse de ce blog
- Article : les nouveautés de C# 5.0
- Modèle Entity Framework généré avec SQL Server 2008 et utilisé sous SQL Server 2005
- Les photos, vidéos et cadeaux des TechDays 2011
- La première journée en ligne sur TechDays TV
- Suivez les TechDays 2011 comme si vous y étiez sur la chaîne TechDays TV
- Téléchargez le programme des conférence des TechDays 2011
- Dernier jour des TechDays = plus de chance de remporter des cadeaux sur le stand de dvp !
- Venez à notre rencontre lors des TechDays 2011
- Les flux à ne pas rater lors des TechDays 2011
- Les TechDays 2011 s’invite sur votre smartphone Windows Phone 7
- Exclu des cadeaux du concours Developpez.com lors des TechDays 2011
- Ouverture de la galerie d’images sur notre site des TechDays
- Partagez votre expérience des Microsoft TechDays
- Grand concours Microsoft “FAN des TechDays 2011” : épisode 2 !
- Mettez-vous aux couleurs des TechDays 2011 !
- Developpez.com aux TechDays 2011
- Le Challenge Azure 2010 est fini !
- Suivez la keynote de la pdc10 en direct sur internet à 18h !
- MVP Visual C# 2010 – 2011 !!!
Merci Vincent pour tes précisions… Je n’ai effectivement pas eu le temps de recopier la fameuse requête en version parallèle :p
ben c’est simple :
var query = from facture in ctx.Factures.Include(« Client »).AsParallel()
select new { factureID = facture.ID, ClientNom = (facture.Client != null) ? facture.Client.Nom : null };
Le problème est le même. Que ce passe t-il si il n’y a pas de Client associé à la facture ? (un indice : NullReferenceException ). Il faut donc avoir un moyen de le tester, et donc revenir à l’écriture « complexe ».
Votre solution ne fonctionne que si l’on est sur (et certain) que chaque facture à un client d’associé …
Il me semble qu’avec Entity Framework on peut pas faire ça, non ?
var query = from facture in ctx.Factures.Include("Client").AsParallel() <br />
select new { factureID = facture.ID, ClientNom = facture.Client.Nom }; <br />
Auquel cas le code n’est pas tellement plus compliqué…
Salut.
En l’occurrence ta requete linq devient :
var query = ctx.Factures.AsParallel().Select(new Func( (f) =>{
f.Client.Load();
Result r = new Result();
r.ID = f.ID;
if( f.Client != null )
r.ClientId = f.Client.ID;
return r;
});
Au passage il faut noter l’abandon de la syntaxe linq pour le passage à la syntaxe « méthodes d’extensions »