56
Présentation Windows 10 pour les développeurs

Présentation Windows 10 pour les développeurs - arati.fr · il change le modèle de distribution et de déploiement des ... adaptable testant la présence d'une fonctionnalité

  • Upload
    doananh

  • View
    214

  • Download
    0

Embed Size (px)

Citation preview

Page 1: Présentation Windows 10 pour les développeurs - arati.fr · il change le modèle de distribution et de déploiement des ... adaptable testant la présence d'une fonctionnalité

Présentation

Windows 10 pour les développeurs

Page 2: Présentation Windows 10 pour les développeurs - arati.fr · il change le modèle de distribution et de déploiement des ... adaptable testant la présence d'une fonctionnalité

2

Genèse de la plateforme Windows 10 ................................................................................................. 4

Architecture de Windows 10 ............................................................................................................... 5

Evolution et cibles ............................................................................................................................ 5

Le modèle applicatif de Windows 10 ................................................................................................... 8

WinRT ............................................................................................................................................... 8

Universal Windows Platform ........................................................................................................... 9

La couche UWP ............................................................................................................................ 9

La pile d'API "traditionnelle", non UWP .................................................................................... 11

La pile UWP / XAML ................................................................................................................... 11

La pile UWP / HTML ................................................................................................................... 11

Les technologies de "bridge" ..................................................................................................... 11

En résumé, comment développer des applications Windows 10 ? ............................................... 13

L'évolution du Framework .Net et de Visual Studio .......................................................................... 14

Roslyn ............................................................................................................................................. 14

Passage en mode Open Source et "out of the band" .................................................................... 15

Les nouvelles plateformes supportées : Linux et OS X .................................................................. 15

Un nouvel outil multiplateformes : Visual Studio Code ................................................................ 15

Optimisations et performances ..................................................................................................... 16

Que change .Net native ? ........................................................................................................... 16

XAML et son optimisation .......................................................................................................... 16

Le développement UWP en XAML ..................................................................................................... 17

Importance de XAML pour Microsoft ............................................................................................ 17

Nouveautés XAML .......................................................................................................................... 17

Performance ............................................................................................................................... 17

Binding compilé .......................................................................................................................... 18

Les design/codage adaptatifs ........................................................................................................ 19

Pratique : « Adaptative UI » et « Adaptative code » ................................................................. 20

Approche 1 : interfaces utilisateur différentes, adaptées à une famille de devices ............. 20

Approche 2 : adapter la même interface utilisateur, à des devices différents ..................... 21

Approche 3 (complémentaire) : utiliser des API d’extension ................................................ 22

Pratique : nouveaux contrôles et layouts .......................................................................................... 23

Architecture : Fichiers et stockage de données ................................................................................. 26

Pratique : utilisation de la base SQLite .............................................................................................. 28

Architecture : la « Microsoft Web Platform » ................................................................................... 31

Pratique : applications HTML 5 Apache Cordova .............................................................................. 32

Page 3: Présentation Windows 10 pour les développeurs - arati.fr · il change le modèle de distribution et de déploiement des ... adaptable testant la présence d'une fonctionnalité

3

Architecture : UWP sur IOT ("Internet of Things") ............................................................................ 35

1 – Plateformes supportées ........................................................................................................... 35

2 – Modèle de programmation ...................................................................................................... 35

Pratique : exemple UWP sur Rasberry Pi 2 .................................................................................... 37

Autres évolutions Visual Studio 2015 ................................................................................................ 39

Survols des nouveautés syntaxiques de C# 6 ................................................................................ 39

Using static ................................................................................................................................. 39

Opérateurs conditionnels null ................................................................................................ 39

Initialiseurs de propriétés automatiques et d'indexeurs ........................................................... 40

Interpolation de chaines ............................................................................................................ 40

Filtres d'exceptions .................................................................................................................... 41

Nouveautés diverses .................................................................................................................. 41

Evolution de C++ ............................................................................................................................ 42

Nouveaux outils de l’IDE ................................................................................................................ 42

Le modèle de distribution .................................................................................................................. 43

Etapes pratiques ............................................................................................................................ 43

Quelle stratégie pour le futur ? .......................................................................................................... 45

Annexe technique 1 - Utilisation d'une architecture MVVM ............................................................ 46

1 – Principes ................................................................................................................................... 46

2 – Exemple .................................................................................................................................... 46

3 – Utilisation d'un framework MVVM .......................................................................................... 48

Annexe technique 2 – programmation asynchrone .......................................................................... 49

1 - Principes et concepts généraux ................................................................................................ 49

2 - Threads et tâches ...................................................................................................................... 50

3 - Continuations ............................................................................................................................ 51

4 - Les mots clés async et await ..................................................................................................... 53

5 – Examen d'un cas d'école : téléchargements asynchrones ....................................................... 54

Page 4: Présentation Windows 10 pour les développeurs - arati.fr · il change le modèle de distribution et de déploiement des ... adaptable testant la présence d'une fonctionnalité

4

Bien que Windows 10 ressemble beaucoup aux versions précédentes de Windows, « sous le capot », les choses sont très différentes et une évolution considérable a eu lieu. Dans cette présentation on va tenter d’en montrer les nouveautés architecturales essentielles, du point de vue du développeur et illustrer tout cela par des exemples de code. Le but est que chacun, en fonction de ses besoins et de sa stratégie pour le futur puisse évaluer les impacts que ces nouveautés vont avoir sur son entreprise et sur ses besoins en acquisition de nouvelles technologies. Commençons par un rapide état des lieux.

Genèse de la plateforme Windows 10 Le but de cette introduction est de rappeler la genèse de l'évolution conduisant à Windows 10. Si on se place 5 ans en arrière : 1 – Microsoft règne sur le poste client et (dans une moindre part), sur le département IT avec ses produits serveurs : Exchange, AD, SQL Server, SharePoint… 2 - Avec sa Xbox Microsoft possède également une part significative du marché du jeu vidéo. 3 – Arrive l'informatique mobile et ses considérables profits, qui va bouleverser la donne. Microsoft est mal préparé à ce virage et Apple / iOS, puis Google / Android se taillent la part du lion. L'approche marketing est très différente également et celle de Microsoft peu adaptée à ce marché. La technologie est également à repenser. L'offre mobile :

Windows Phone 7 et 7,5 sortent en 2010 et 2011 et succèdent à Windows Mobile. Evolution de la plateforme desktop

Windows 7 est la dernière version de Windows purement desktop. Le but de Microsoft est de produire la convergence de ses plateformes, et Windows 8 / 8,1 en forment l'amorçage. Même si ces OS ne sont pas des succès commerciaux, ils sont l’occasion de préparer la véritable avancée : un Windows unique pour toutes les plateformes. Le projet Windows 10 est très ambitieux car :

il unifie et fait évoluer des anciennes technologies

il change le modèle de distribution et de déploiement des applications.

il intègre des technologies concurrentes, ou en tous cas différentes des technologies "maison", ce qui dénote une indéniable volonté d'ouverture.

Il s'ouvre vers de nouveaux devices matériels : IoT, Hololens, Surface…

Ses déclinaisons d’OS utilisent un noyau commun (depuis Windows 8,0)

Ainsi (et c’est encore plus important) qu’une APÏ commune (présente partiellement avec

Page 5: Présentation Windows 10 pour les développeurs - arati.fr · il change le modèle de distribution et de déploiement des ... adaptable testant la présence d'une fonctionnalité

5

Windows 8,1 et complètement avec Windows 10).

un Framework commun et à couplage contrôlé, et porté sous MacOs et Linux.

des outils de développement communs (dans Visual Studio, devenue une boite à Outils universelle).

des technologies variées : basées sur le Web (interface HTML 5 codée en JavaScript) ou traditionnelle (XAML + .Net).

intégration des technologies externes voire concurrentes : Apache Cordova, applications Android, applications iOS…

volonté d'aller vers le marché de l'embarqué (IoT). Il est évident que cette évolution est essentielle pour Microsoft : une plateforme unifiée est très attirante pour les développeurs qui vont alimenter le Windows Store et Microsoft a impérativement besoin d’eux pour offrir des applications crédibles à son offre mobile.

Architecture de Windows 10

Evolution et cibles

La convergence de ses OS, qu'il s'agisse du desktop, de l'OS mobile, ou de la console Xbox s'est faite en plusieurs étapes :

1. Convergence des noyaux. Ce premier travail, colossal et pratiquement invisible de l'extérieur, est la fondation du reste. Il correspond aux versions Xbox One / Windows 8 / Windows Phone 8. C'est aussi à cette occasion que l'API WinRT a été définie dans Windows 8.

2. Convergence partielle des modèles applicatifs. Pour les développeurs, à partir de Windows 8.1 / Windows Phone 8.1 les modèles applicatifs fusionnent et on parle pour la première fois d'"applications universelles", c'est à dire ciblant WinRT, dans sa déclinaison desktop et mobile.

3. Convergence totale des modèles applicatifs et ajout d'autres plateformes. Windows 10

Page 6: Présentation Windows 10 pour les développeurs - arati.fr · il change le modèle de distribution et de déploiement des ... adaptable testant la présence d'une fonctionnalité

6

parachève ce travail, en poursuivant ce qui a été commencé, le même modèle applicatif fonctionnant maintenant sur toutes les déclinaisons de l'OS.

En même temps, Microsoft cible désormais un grand nombre de terminaux différents :

Ils ont été regroupés en familles : En plus des traditionnels PC, mobiles/tablettes et Xbox, on y découvre :

Surface Hub, avec un écran de 84 ou 55 pouces (2m10 ou 1m40), pour effectuer des présentations interactives.

Page 7: Présentation Windows 10 pour les développeurs - arati.fr · il change le modèle de distribution et de déploiement des ... adaptable testant la présence d'une fonctionnalité

7

A l'autre extrémité de l'échelle de taille, on trouve le support des "objets connectés" ("Internet of Things" ou "IoT"), à travers des cartes comme le Rasberry Pi 2 (processeur ARM) ou Intel Galileo (processeur x86).

Enfin, Hololens un device de réalité augmentée, non encore disponible pour le grand public, mais dont le kit de développement est proposé en précommande aux développeurs US (et seulement US, pour le moment…) pour 3000 $, qui sera livré à partir du premier trimestre 2016.

Page 8: Présentation Windows 10 pour les développeurs - arati.fr · il change le modèle de distribution et de déploiement des ... adaptable testant la présence d'une fonctionnalité

8

Le modèle applicatif de Windows 10 Pour les développeurs, l’aspect essentiel est l’interface de programmation du nouvel OS. Pour comprendre ce modèle il n'est pas inutile de revenir un peu en arrière, au modèle proposé par WinRT (Windows 8 / 8.1), dont l'UWP est une extension.

WinRT

En voici un schéma d’architecture simplifiée :

On voit que WinRT propose une couche native (basée sur COM "étendu"), donnant accès à un ensemble de services : interface utilisateur (avec le support natif de XAML), réseau, threading etc. tous considéré comme "sûrs". Une application WinRT n'a pas accès à l'ensemble des services de l'OS, mais uniquement à un cœur fonctionnel. Cela sera le même cas, avec UWP. Bien que WinRT soit codé en C++, ses primitives sont "projetées" dans plusieurs langages de plus haut niveau, membre de la famille .Net. Les types WinRT apparaîtront pour eux comme des types .Net, bien qu'ils n'en soient pas. On notera qu'à travers la VM d'IE, une application HTML / JavaScript pourra également accéder aux couches bases natives de WinRT. Là encore, Edge (le nouveau navigateur Microsoft) propose des services similaires dans Windows 10. Enfin, WinRT promeut largement un modèle asynchrone de programmation, pour toutes les primitives dont le temps d'exécution dépasse 50 ms. Cette architecture est à l'origine de l'API de "l'Universal Windows Platform" qui en reprend la structure. Ainsi, les développeurs ayant travaillé avec WinRT vont se retrouver en pays de connaissance...

Page 9: Présentation Windows 10 pour les développeurs - arati.fr · il change le modèle de distribution et de déploiement des ... adaptable testant la présence d'une fonctionnalité

9

Universal Windows Platform

Voici une vue synoptique de la plateforme UWP :

La couche UWP

Elle reprend la structure de WinRT, étendue à toutes les plateformes supportées. Ce qui caractérise UWP :

on ne cible pas un OS, mais une famille de devices. Chaque famille supporte le même cœur d'API + des APIs spécifiques fournies par des Frameworks d'extension.

Sa distribution peut se faire à travers un store unique.

Le packaging des applications utilise un format spécifique (.appx, une variante du format zip).

Les contrôles UWP savent s'adapter au device hôte, et le code de l'application peut également aider à l'adaptation (design et code adaptatifs, vus plus loin).

Le principe n'est pas d'avoir une application unique, "passe-partout", avec un commun dénominateur, mais de permettre l'utilisation complète des possibilités de chaque device. Pour cela, en plus du cœur UWP, des extensions spécifiques permettent l'écriture de code adaptatif (si le device est le bon, le code spécifique sera activé pendant l'exécution, le développeur pouvant dynamiquement analyser la présence ou l'absence de telle ou telle fonctionnalité) :

Page 10: Présentation Windows 10 pour les développeurs - arati.fr · il change le modèle de distribution et de déploiement des ... adaptable testant la présence d'une fonctionnalité

10

La présence d'extensions dans un binaire UWP ne créera pas de problème sur un device ne les supportant pas. En fait, bien que toutes les APIs soient présentes sur chaque device (pour permettre la compilation), seules certaines d'entre elles sont effectivement connectées à un device hardware présent :

Bien sûr si on ne cible qu'un seul device, ce code adaptatif sera superflu. Les applications UWP utilisent le paradigme du "tailored design". Suivant Microsoft on distingue :

le "responsive design" où l'application/site s'adapte à la taille de l'écran.

l' "adaptative design" où l'application intercepte plus profondément les actions de l'utilisateur (rotation du téléphone etc.).

le "tailored design" où l'application, en fonction de la famille de devices active/désactive certaines fonctionnalités (basées sur des APIs d'extension). Pour cela on utilisera du code adaptable testant la présence d'une fonctionnalité hardware et l'utilisant conditionnellement.

Page 11: Présentation Windows 10 pour les développeurs - arati.fr · il change le modèle de distribution et de déploiement des ... adaptable testant la présence d'une fonctionnalité

11

La pile d'API "traditionnelle", non UWP

Il est toujours possible (et Microsoft entend bien maintenir cette possibilité) de développer des applications "non UWP" en utilisant les piles d'API traditionnelles (Win32, COM, .Net full) pour des applications ne souhaitant pas sortir du cadre du desktop. Ainsi WPF et WinForms restent pertinents et sont maintenus.

La pile UWP / XAML

C'est l'approche "préférentielle" de développement. XAML est une technologie qui a fortement évolué récemment (voir plus loin). Microsoft semble l'utiliser de plus en plus complètement pour ses développements internes (Office et Windows lui-même). En ce qui concerne les langages, 3 sont supportés pour le moment : C# / VB.Net / C++ CX. Il faut noter que l'ensemble du Framework .Net n'est pas disponible pour le développement UWP mais seulement .Net Core. D'autre part, les applications sont désormais compilées nativement par .Net native.

La pile UWP / HTML

Cette possibilité, amorcée avec WinRT, est toujours présente avec Windows 10. L'application va alors accéder à UWP à travers la VM du navigateur, Edge dans le cas de Windows 10. Le développeur peut utiliser les Frameworks Open Source qu'il souhaite, comme Angular JS et Ember JS. Microsoft encapsule de nombreuses fonctionnalités d'interface utilisateur et de binding dans WinJS, qui peut être utilisée conjointement à Apache Cordova, également supporté par Visual Studio (voir plus loin).

Les technologies de "bridge"

Le but de ces technologies est de permettre de porter à moindre coût des projets existant dans d'autres technologies vers UWP, et ainsi, d'en enrichir l'écosystème, sans exiger des développeurs de réécrire complètement leur application. Microsoft travaille sur les bridges suivants (leur disponibilité n'étant pas encore forcément effective) :

Bridge iOS Son but : à partir d'un projet Xcode ObjectiveC, après des modifications "mineures", le recompiler et produire une application UWP. Les outils ObjectiveC sont déjà disponibles dans Visual Studio 2015 RTM.

Bridge Android

Page 12: Présentation Windows 10 pour les développeurs - arati.fr · il change le modèle de distribution et de déploiement des ... adaptable testant la présence d'une fonctionnalité

12

De même que pour iOS, le bridge Android (projet "Astoria") permettra, à partir de code Java, de produire une application UWP. Un émulateur Android, basé sur Hyper-V, est également disponible et fourni par Microsoft (!).

Bridge Web ("Web hosted apps") Le principe est d'inclure dans une application UWP le contenu d'un site web, avec la possibilité d'accéder, en plus aux fonctionnalités de bas niveau du terminal, à travers JavaScript.

Bridge Win32 Packaging d'applications Win32 et .Net sous forme d'applications UWP, élligibles à la publication sur le Windows Store (disponible en 2016).

Page 13: Présentation Windows 10 pour les développeurs - arati.fr · il change le modèle de distribution et de déploiement des ... adaptable testant la présence d'une fonctionnalité

13

En résumé, comment développer des applications Windows 10 ?

En fonction de qui je suis, c'est différent ! 1 - Je suis un développeur d'application d'entreprise de gestion ou d'administration système.

Est-ce que je veux cibler UWP ? ◦ Si oui, quelle technologie vais-je utiliser ?

▪ XAML avec C#, VB ou C++. Voie initiée par WPF / SilverLight / Windows Phone et les applis WinRT "conventionnelles". C'est la "voie royale", une évolution historique normale. Une partie de Windows 10 (menu de démarrage, par exemple) et même d'Office 2016 utilise désormais le "nouveau XAML optimisé" (voir plus loin).

◦ Si non, par exemple pour des applications d'entreprises non destinées à la mobilité (type applications LOB) ou des applications Web ASP.Net MVC, on conservera la stack traditionnelle (WPF etc.)

2 - Je suis un développeur Web et je souhaiterais créer une application UWP

HTML 5 / JavaScript. Utilisation de WinJS et/ou Apache Cordova. Je ferais ce choix si je suis (très) expérimenté avec JavaScript et ses Frameworks (Angular JS, Backbone, Ember...) et désireux de monter en compétence sur WinJS.

Je peux éventuellement packager un site web existant en une application Windows 10 en utilisant le bridge des "hosted apps".

3 - Je suis un développeur embarqué, (utilisant par exemple un Linux embarqué ou un OS temps réel), et je suis désireux d'explorer la nouvelle plateforme IoT.

UWP avec ses extensions devices. Le modèle de travail est toujours une application UWP, typiquement en XAML. Le Framework .Net ajoute des namespaces spécifiques au matériel ciblé (GPIO, I2C, SPI etc.).

4 - Je suis déjà développeur d'applications iOS ou Android que je souhaite porter vers Windows 10.

si ce sont des applications natives iOS ou Android, je peux utiliser les outils d'émulation / conversion vers UWP pour aider à les porter (les "bridges" UWP).

Si ce sont des applications PhoneGap / Cordova, je peux aisément les migrer vers Windows 10 grâce au support de Cordova dans Visual Studio.

Page 14: Présentation Windows 10 pour les développeurs - arati.fr · il change le modèle de distribution et de déploiement des ... adaptable testant la présence d'une fonctionnalité

14

L'évolution du Framework .Net et de Visual Studio En tant que développeurs, sur les plateformes Microsoft, on a longuement côtoyé le Framework .Net et les langages qui y sont associés (C# / VB.Net et C++ CX). Microsoft évalue à 6 millions le nombre de développeurs .Net. Il va de soi que les évolutions de cette infrastructure auront des conséquences importantes. Voici un résumé de(s) dernière(s) déclinaisons de .Net :

Ainsi qu'on le constate, il est subdivisé en 4 grandes parties (du bas vers le haut) :

un environnement partagé par les diverses implémentations : l'infrastructure de compilation ("Roslyn"), l'environnement d'exécution (dont RyuJIT, le nouveau compilateur 64 bits JIT) et le gestionnaire de packages Nuget.

Le "bon vieux" Framework .Net présent sous Windows (version 4,6). On notera que cela n'est PAS celui placé sous le modèle d'applications "Universal Windows Apps". Son modèle de distribution reste monolithique et tous ses composants évoluent en même temps.

.Net Core, qui est un port Open Source d'un sous-ensemble du Framework complet. Son organisation en modules découplés en permet une évolution bien plus souple et non monolithique. Il en existe un port Linux et OS X en cours, opéré par Microsoft lui-même… Il peut parfaitement être déployé avec une application et n'a pas besoin d'être précédemment installé.

Des modèles applicatifs traditionnels (posés sur le Framework complet Windows, comme WPF, WinForms et ASP.Net 4.x et 5) et récents (ASP.Net 5, UWP) fondamentalement multiplateformes (local, cloud) et multi-OS (Windows 10, Linux, OS X).

Roslyn

Roslyn est l'aboutissement de 6 ans d'efforts pour Microsoft. Il s'agit de la réécriture complète de ses outils de compilation et de ses langages en code .Net et non natif. En considérant les outils de

Page 15: Présentation Windows 10 pour les développeurs - arati.fr · il change le modèle de distribution et de déploiement des ... adaptable testant la présence d'une fonctionnalité

15

compilation comme une plateforme modulaire et non plus monolithique, il est plus facile de les faire évoluer et de les maintenir. Les langages .Net sont désormais une partie de Roslyn. Nous évoquerons plus loin leurs nouveautés. Tous les outils Roslyn sont désormais Open Source. Voir https://github.com/dotnet/roslyn.

Passage en mode Open Source et "out of the band"

Pour dépasser la lourdeur de l'évolution par versions complètes du Framework .Net, Microsoft en a extrait le cœur (".Net Core") et en a l'a déconnecté des dépendances avec les autres éléments du Framework. .Net Core est un projet pleinement open source basé sur GitHub mais soumis aux mêmes contraintes de qualité que le code propriétaire interne de Microsoft. IL est en cours de portage vers OS X et Linux par Microsoft lui-même. De nombreux sous-ensembles du Framework .Net traditionnel, vont suivre le même chemin d'évolution. Ainsi Entity Framework 7 a été complètement réécrit pour être découplé du Framework complet et "posé" simplement sur .Net Core. Il pourra ainsi être utilisé sur les plateformes qu'il supporte (le cloud, IoT, Linux etc.).. Encore une fois, l'un des plus grands avantage de cette approche est la possibilité pour chaque bibliothèque d'évoluer rapidement, individuellement, découplée ("out of the band") des releases de l'ensemble du Framework.

Les nouvelles plateformes supportées : Linux et OS X

Un grand vent d'ouverture "raisonnée", mais bien réelle, souffle chez Microsoft. A la formulation des années 2001 de Steve Ballmer ("Linux is a cancer !") succède désormais le non moins fameux :

du PDG Satya Nadella ! Le pragmatisme et l'ouverture d'esprit sont en effet certainement plus payant que l'hostilité. En plus de .Net Core, ASP.Net 5 (disponible début 2016) sera également disponibles sous Linux et OS X, ainsi que Visual Studio Code.

Un nouvel outil multiplateformes : Visual Studio Code

Page 16: Présentation Windows 10 pour les développeurs - arati.fr · il change le modèle de distribution et de déploiement des ... adaptable testant la présence d'une fonctionnalité

16

En plus de porter .Net Core sous Linux et OS X, Microsoft propose également un éditeur / debugger "orienté code" pour travailler sur des applications Web (ASP.Net 5) et JavaScript (Node JS …) disponible également prochainement sur les plateformes supportées (Windows, Linux, OS X). Il n'est pas question, pour le moment, de porter complètement Visual Studio sur ces plateformes.

Optimisations et performances

Pour terminer ce tour d'horizon rapide des nouveautés du Framework, plusieurs optimisations significatives sont intervenues.

Que change .Net native ?

Ainsi qu'on l'a déjà évoqué, un nouveau compilateur JIT 64 bits est désormais disponible et fait partie de la plateforme Roslyn. Mais surtout, désormais les applications .Net sont compilées nativement lorsque l'on compile l'application en mode « release ». Le compilateur AOT ("Ahead Of Time") utilisé est issu de la technologie Visual C++, et fournit donc des performances similaires.

XAML et son optimisation

L'importance stratégique de XAML pour Microsoft l'a fait investir dans de nombreuses optimisations. Citons en deux :

une évaluation du binding en phase de compilation (attribut "{x:bind }"), en plus du binding dynamique {Binding } "classique".

Le chargement différé ("lazy loading") des éléments d'interfaces les plus lourds.

Page 17: Présentation Windows 10 pour les développeurs - arati.fr · il change le modèle de distribution et de déploiement des ... adaptable testant la présence d'une fonctionnalité

17

Le développement UWP en XAML Pour construire les interfaces utilisateurs UWP, Microsoft propose 2 voies :

Utilisation de XAML (« XML Application Markup Language »), qui existe depuis 10 ans, mais qui a été modifié par rapport aux versions précédentes. C’est une approche similaire à celle suivie par les concurrents : Google et Apple définissent également leurs UI ainsi.

Utilisation d’HTML 5 s’exécutant dans le navigateur Edge. Pour bénéficier des fonctionnalités bas niveaux de l’OS, inaccessible normalement au code s’exécutant dans la « sandbox » du navigateur, il faut donc une librairie JavaScript permettant d’y accéder. Dans le cas d’UWP on pourra utiliser Cordova et/ou WinJS. Les deux sont pleinement supportées par Microsoft.

On va examiner successivement (rapidement…) ces technologies en insistant sur XAML qui est clairement l’approche de prédilection de Microsoft.

Importance de XAML pour Microsoft

Cette approche, clairement la voie préférentielle de Microsoft, et capitalise sur ses approches du passé : WPF et Silverlight et les applications Windows 8 / 8,1 (desktop et mobile). La technologie XAML a été adoptée en profondeur par toutes les divisions de Microsoft :

Office 2016 l'utilise, et l’équipe Office (qui code en C++) est à l'origine de nombre de ses nouvelles optimisations.

Nombre des applications standard de Windows sont désormais codées en XAML.

Le menu de démarrage de l'OS Windows 10 s'en sert également.

Nouveautés XAML

Performance

La dernière version de XAML a amélioré la performance :

rapidité de démarrage (dépend de la complexité de l'arbre des composants visuels).

rapidité du rendu visuel (affichage et gestion mémoire).

Rapidité du temps de réponse à l'utilisateur (y compris le scrolling intensif). Le passage de Windows 8.x à Windows 10 s'accompagne d'une amélioration notable (en plus de l'optimisation de XAML) :

Page 18: Présentation Windows 10 pour les développeurs - arati.fr · il change le modèle de distribution et de déploiement des ... adaptable testant la présence d'une fonctionnalité

18

De nouvelles techniques d'optimisation ont fait leur apparition :

1. Chargement différé ("defered loading") des composants : ils peuvent n'être chargé qu'au fur et à mesure de leur nécessité (en utilisant la méthode FindName()). L'élément à charger en mode "lazy" doit être marqué ainsi :

x:DeferLoadStrategy="Lazy" 2. Virtualisation des données : chargement incrémental lors du parcourt et accès aléatoire

dans des listes d’affichage de données de grande taille (sélection d'une page de données à charger).

Binding compilé

La grande force de XAML a toujours été son intégration profonde du binding, permettant de connecter des éléments de l’interface utilisateur à des objets de code (classes « code behind » ou ViewModels du pattern MVVM). Ce binding était jusqu’à présent basé sur l’API de réflexion et donc évalué pendant l’exécution, ce qui avait pour conséquence :

D’être lent (l’analyse par réflexion est lente).

D’offrir un support « moyen » au débogage. Exemple de notation de binding « classique » : <Grid Grid.Column="1" TextBlock.FontSize="16"

DataContext="{Binding SelectedItem, ElementName=lstMaitre}"> …

<TextBlock Grid.Row="1" Margin="6" Text="{Binding Id, StringFormat='Id : 0'}" /> … </Grid> Il existe désormais, ajouté au précédent modèle de binding, un modèle compilé, sans analyse à l’exécution qui est donc nettement plus rapide et privilégié par rapport au précédent. Exemple de notation de binding compilé : <SplitView x:Name="SplitView" Grid.Row="1"

IsPaneOpen="{x:Bind ViewModel.IsSplitViewPaneOpen, Mode=TwoWay}" > …

Page 19: Présentation Windows 10 pour les développeurs - arati.fr · il change le modèle de distribution et de déploiement des ... adaptable testant la présence d'une fonctionnalité

19

Les design/codage adaptatifs

Afin de supporter de façon complète les diverses plateformes supportées, avec leurs tailles d’écran si différentes (de 4 à 80 pouces…), Microsoft recommande une approche « adaptative » dans la conception des interfaces utilisateurs. Plusieurs approches sont possibles :

Le plus simple est de cibler uniquement une famille de terminaux (comme un device IoT, par exemple). C’est parfois nécessaire si l’application que l’on écrit requiert absolument cette famille.

Si on veut une application plus souple, il faut : 1. Qu’elle puisse « s’auto-adapter » dans son interface utilisateur à la taille de l’écran,

au type de device ou à toute condition définie dans le code (pas de connexion Internet, …).

2. Qu’elle puisse tirer parti dans son code, de la présence de ressources matérielles et logicielles propres à une famille spécifique de devices.

On parle dans ce cas de design et de code adaptatifs, qui vont conditionnellement, donner accès à des fonctionnalités, suivant les possibilités du terminal ou de l’environnement. En effet, le but n’est pas de faire des applications qui sont des « communs dénominateurs » minimalistes à toutes les plateformes supportées, mais au contraire, des applications tirant pleinement parti des possibilités du terminal. Ce n’est, bien sûr, pas évident… Les contrôles standards eux-mêmes (comme la CommandBar) sont conçus pour s'adapter au device sur lesquels ils tournent, ainsi qu'au type d'interaction utilisée (toucher ou souris). D’autre part, pour dimensionner les éléments, le système applique un algorithme de mise à l'échelle prenant en compte la taille du device mais également la distance à laquelle on le consulte. Ainsi sur 3 écrans de taille différente, la même application affichera :

Page 20: Présentation Windows 10 pour les développeurs - arati.fr · il change le modèle de distribution et de déploiement des ... adaptable testant la présence d'une fonctionnalité

20

Pour représenter les tailles des éléments on utilise en fait les "pixels effectifs", appliquant un correctif d'adaptation à la densité et la distance de consultation du terminal :

Les pixels utilisés en XAML sont donc toujours de ce type. En ce qui concerne le design de l'UI, Microsoft conseille de se baser sur 3 tailles principales :

le téléphone (5", mode portrait)

la tablette (8", mode paysage)

l'ordinateur (13", mode paysage) Trois approches sont conseillées :

1. Responsive design : redimensionnement automatique. 2. Adaptive Design : lorsque l'approche 1 ne suffit plus, on déplace ou on transforme

l'interface (exemple « classique » : application maitre/détails). 3. Tailored design : un design spécifique pour une famille de devices spécifiques. Un exemple

en est l'application IoT Rasberry Pi vue plus loin.

Pratique : « Adaptative UI » et « Adaptative code »

On va maintenant examiner la mise en pratique de ces démarches d’adaptation d’une application aux devices sur lesquels elle tourne.

Approche 1 : interfaces utilisateur différentes, adaptées à une famille de devices

Projet exemple : SplitViewMini, solution ExemplesSimples Dans ce projet, on a décidé de fournir 2 versions pour les pages « Page1 » et « Page2 » : une pour

Page 21: Présentation Windows 10 pour les développeurs - arati.fr · il change le modèle de distribution et de déploiement des ... adaptable testant la présence d'une fonctionnalité

21

la version « desktop » de l’application et une pour la version « mobile ». Pour faire cela, on a le choix :

Soit de modifier le nom de la page. Ainsi, la version « mobile » de Page2.xaml deviendra Page2.DeviceFamily-Mobile.xaml et les deux coexisteront dans le projet (voir image ci-dessous).

Soit de placer les deux pages (qui, alors, auront le même nom) dans deux répertoires différents. On doit alors créer le répertoire de nom « magique » DeviceFamily-Mobile :

On note également que ce principe s’applique aux ressources : dans le répertoire Theme (image ci-dessus) il existe deux versions pour le fichier de ressources Specifique.xaml. On utilisera cette solution s’il n’est pas possible de travailler avec des définitions d’UI car les devices sont trop différents.

Approche 2 : adapter la même interface utilisateur, à des devices différents

Projets exemples : SplitViewMini et SplitViewApp1, solution ExemplesSimples Cette seconde approche consiste en l’adaptation d’une seule version de l’interface utilisateur afin qu’elle se « plie » au device où elle est déployée. Le mécanisme nouveau le plus important pour cela est la gestion des « Visual States ». Un Visual State permet de définir un ensemble de propriétés de l’interface utilisateur, et de les appliquer uniquement si une condition (un « trigger ») est satisfaite. Ces conditions peuvent être :

La résolution de l’écran.

Le type de device courant.

N’importe quelle décision prise par le code (« trigger custom », sous forme d'une classe dérivée de StateTriggerBase).

Si on souhaite changer, par exemple, l’apparence d’un contrôle (ici un SplitView) suivant la taille de l’écran on pourra définir, dans le XAML (MainPage.xaml, projet SplitViewMini) : <VisualState x:Name="VeryWideState"> <VisualState.StateTriggers> <AdaptiveTrigger MinWindowWidth="1024" /> </VisualState.StateTriggers> <VisualState.Setters> <Setter Target="MaSplitView.DisplayMode" Value="Inline" /> <Setter Target="MaSplitView.IsPaneOpen" Value="True" /> </VisualState.Setters>

Page 22: Présentation Windows 10 pour les développeurs - arati.fr · il change le modèle de distribution et de déploiement des ... adaptable testant la présence d'une fonctionnalité

22

</VisualState> En français : « si la largeur de l’écran est d’au moins 1024 pixels effectifs, on affecte ‘Inline’ à la propriété DisplayMode du contrôle SplitView et True à sa propriété IsPaneOpen ». Par code on peut également forcer un état spécifique via VisualStateManager.GoToState(). Il est possible de créer des triggers customs, activé dans le XAML, et Une autre solution est de créer un trigger custom (voir exemple standard VisibleBoundsDemo) et, dans le XAML, pour contrôler l'interface utilisateur en fonction du type de device présent, on utilisera (en précisant la famille ciblée, par exemple Desktop ou Mobile) :

<VisualState.StateTrigger> <triggers:DeviceFamilyTrigger DeviceFamily="Desktop"> </VisualState.StateTrigger>

Approche 3 (complémentaire) : utiliser des API d’extension

Projet utilisé : SplitViewMini Si on examine les références de ce projet, dans le volet Extensions, on observe :

Comme cette application doit s’exécuter sur la plate-forme Desktop et Mobile, on a ajouté à UWP (le cœur ‘neutre’ de l’API) les deux bibliothèques d’extensions correspondantes. Cependant, ces APIs d'extension quoique disponibles, ne s'appliquent pas uniformément à tous les devices, un test est donc nécessaire avant de les invoquer, même si elles sont présentes dans l'application (exemple : présence d'un bouton back). En effet, les codes sont binairement compatibles pour toutes les plateformes UWP. Une partie de l'API peut être appelée librement ("freely"), c'est le cœur UWP, mais le reste, situé dans les extensions, doit être appelé conditionnellement.

Page 23: Présentation Windows 10 pour les développeurs - arati.fr · il change le modèle de distribution et de déploiement des ... adaptable testant la présence d'une fonctionnalité

23

Le code adaptatif va donc conditionnellement exécuter du code suivant la famille de devices en présence et/ou en fonction de la version de la plateforme courante. Pour savoir si une API est bien réalisée sur un device on utilisera la classe Windows.Foundation.Matadata.ApiInformation et on appellera une des méthodes Is*Present(), par exemple IsTypePresent(NomDuType). Dans le cas où ce test n'est pas effectué, on obtiendra une TypeLoadException lors de la tentative d'utilisation du type absent. Note : on n'utilise PAS dans ce cas la compilation conditionnelle, contrairement à Windows 8.x.

Pratique : nouveaux contrôles et layouts Les contrôles WinRT existants ont été augmentés de quelques ajouts forts utiles pour les nouvelles missions de la plate-forme UWP. Nous allons seulement évoquer ici le nouveau contrôle SplitView et un nouvel outil de layout, le RelativePanel. Si on souhaite une revue exhaustive des contrôles UWP, le mieux est de jeter un œil sur les ‘samples UWP’, disponibles sur GitHub (https://github.com/Microsoft/Windows-universal-samples) qui sont très complets. On regardera particulièrement l’exemple UIBasics qui présente exhaustivement chacun d’entre eux. Projets exemples : SplitViewMini et SplitViewApp1, solution ExemplesSimples

Page 24: Présentation Windows 10 pour les développeurs - arati.fr · il change le modèle de distribution et de déploiement des ... adaptable testant la présence d'une fonctionnalité

24

On y voit, à gauche, le contrôle SplitView et son panel déroulé (contenant 4 options de menu) et, à sa droite, une page chargée dans sa zone de contenu. Ce contrôle est bien adapté à l’environnement UWP, car son panel est plus ou moins « encombrant » :

Ces divers modes de recouvrement du contenu peuvent être pilotés par des triggers de Visual States et donc être adaptés aisément à la taille de l’écran : <VisualStateManager.VisualStateGroups> <VisualStateGroup x:Name="WindowStates">

<VisualState x:Name="WideState"> <VisualState.StateTriggers> <AdaptiveTrigger MinWindowWidth="720" /> </VisualState.StateTriggers> <VisualState.Setters> <Setter Target="SplitView.DisplayMode" Value="CompactInline" /> </VisualState.Setters> </VisualState> <VisualState x:Name="NarrowState"> <VisualState.StateTriggers> <AdaptiveTrigger MinWindowWidth="0" /> </VisualState.StateTriggers> <VisualState.Setters> <Setter Target="SplitView.DisplayMode" Value="Overlay" /> </VisualState.Setters> </VisualState> </VisualStateGroup> </VisualStateManager.VisualStateGroups> Le RelativePanel, quant à lui, permet de placer les contrôles relativement les uns aux autres (comme son nom l’indique…), et, associé aux Visual states de modifier aisément leurs emplacements en fonction de la résolution de l’écran (page Page3.xaml, projet SpliViewApp1) : <RelativePanel> <TextBlock Text="Nom " Name="tbkNom" Margin="10" Width="100" * RelativePanel.AlignLeftWithPanel="True" />

Page 25: Présentation Windows 10 pour les développeurs - arati.fr · il change le modèle de distribution et de déploiement des ... adaptable testant la présence d'une fonctionnalité

25

<TextBlock Text="Prénom " Name="tbkPrenom" Margin="10" Width="100" RelativePanel.AlignLeftWithPanel="True"/>

<TextBlock Text="Email " Name="tbkEmail" Margin="10" Width="100" RelativePanel.AlignLeftWithPanel="True"/>

<TextBox Name="tbxNom" Width="400" /> <TextBox Name="tbxPrenom" Width="400" /> <TextBox Name="tbxEmail" Width="400" /> </RelativePanel> Aucune logique de positionnement pour ces contrôles n’est définie ci-dessus, c’est le rôle des groupes suivant de Visual States, situés plus bas dans la même page, qui vont placer les contrôles en fonction de la largeur courante de l’écran : <VisualStateGroup x:Name="LargeurFenetre"> <VisualState x:Name="Etroite"> <VisualState.StateTriggers> <AdaptiveTrigger MinWindowWidth="0" /> </VisualState.StateTriggers> <VisualState.Setters> <Setter Target="tbxNom.(RelativePanel.Below)" Value="tbkNom" /> <Setter Target="tbkPrenom.(RelativePanel.Below)" Value="tbxNom" /> <Setter Target="tbxPrenom.(RelativePanel.Below)" Value="tbkPrenom" /> <Setter Target="tbkEmail.(RelativePanel.Below)" Value="tbxPrenom" /> <Setter Target="tbxEmail.(RelativePanel.Below)" Value="tbkEmail" /> </VisualState.Setters> </VisualState> <VisualState x:Name="Large"> <VisualState.StateTriggers> <AdaptiveTrigger MinWindowWidth="720" /> </VisualState.StateTriggers> <VisualState.Setters> <Setter Target="tbxNom.(RelativePanel.RightOf)" Value="tbkNom" /> <Setter Target="tbxNom.(RelativePanel.AlignVerticalCenterWith)" Value="tbkNom"/> <Setter Target="tbkPrenom.(RelativePanel.Below)" Value="tbkNom"/> <Setter Target="tbxPrenom.(RelativePanel.RightOf)" Value="tbkPrenom"/> <Setter Target="tbxPrenom.(RelativePanel.AlignVerticalCenterWith)" Value="tbkPrenom"/> <Setter Target="tbkEmail.(RelativePanel.Below)" Value="tbkPrenom"/> <Setter Target="tbxEmail.(RelativePanel.RightOf)" Value="tbkEmail"/> <Setter Target="tbxEmail.(RelativePanel.AlignVerticalCenterWith)" Value="tbkEmail"/> </VisualState.Setters> </VisualState> Si l’écran est assez large les zones de saisie seront placées à droite des étiquettes, sinon dessous :

Page 26: Présentation Windows 10 pour les développeurs - arati.fr · il change le modèle de distribution et de déploiement des ... adaptable testant la présence d'une fonctionnalité

26

Architecture : Fichiers et stockage de données L’architecture UWP ne permet pas, pour des raisons de sécurité l’accès à l’ensemble du système de fichier pour une application issue du Windows Store (de façon similaire à ce que l’on trouve dans les environnements IOS et Android). Pour accéder aux emplacements autorisés il faudra généralement passer par des « file pickers ». Les divers emplacements autorisés pour l’application, sont représentés sur l’image suivante :

Le rôle de chacun de ces emplacements est différent et synthétisé par la figure suivante :

Le répertoire Roaming est synchronisé à travers le Cloud avec une taille max de 100 ko synchronisables. Les "KnownFolders" sont des moyens de simplifier l'accès aux fichiers en organisant le stockage par types (images, vidéos, musique). Pour y accéder l'application doit le demander dans ses permissions. Il existe une API spécifique pour les « settings », les préférences (un dictionnaire de clés/valeurs).

Page 27: Présentation Windows 10 pour les développeurs - arati.fr · il change le modèle de distribution et de déploiement des ... adaptable testant la présence d'une fonctionnalité

27

L’application elle-même a accès à son répertoire d’installation et peut créer, à travers les API sécurisées de WinRT, des fichiers de préférences, des fichiers « généralistes » ou bien des fichiers de bases de données pour du stockage structuré :

Depuis l’application, on pourra utiliser une syntaxe D’URI pour accéder à ces divers emplacements :

Ainsi, dans un exemple Cordova (application HTML 5, voir plus loin), pour accéder à un fichier audio et le jouer via l’API multimédia, on utilisera : if (device.platform === "windows")

{

cordova.file = {applicationDirectory: 'ms-appx-web://jqmcordova/'};

}

En ce qui concerne les bases de données, il n’est pas question ici de serveurs de bases de données comme SQL Server, mais de moteurs locaux, ‘in process’. Le plus connu et utilisé, et recommandé d’ailleurs par Microsoft, est SQLite.

Page 28: Présentation Windows 10 pour les développeurs - arati.fr · il change le modèle de distribution et de déploiement des ... adaptable testant la présence d'une fonctionnalité

28

Pratique : utilisation de la base SQLite Pour utiliser cette base de données, la première étape consiste à ajouter à Visual Studio l’extension « SQLite for Universal App Platform », qui met le moteur de la base à disposition de l’application, ce qui est nécessaire pour les deux exemples vus maintenant :

On va utiliser successivement deux approches :

Utilisation d’un moteur d’accès non-Microsoft, SQLite.Net (voir https://github.com/praeclarum/sqlite-net).

Utilisation D’Entity Framework 7 (beta), la nouvelle version de ce composant majeur d’ADO.Net, repackagé pour être complètement indépendant du « gros » Framework .Net et ne dépendre que de .Net Core et pouvoir ainsi être pleinement multiplateformes (cloud, UWP, Linux, OS X…). Pour plus de détails voir https://github.com/aspnet/EntityFramework.

Projet exemple SQLiteStd, dont voici une copie d’écran, lors de l’exécution (noter le chemin du fichier de base de données) :

Dans cet exemple on va enregistrer dans une table une collection d’entités : public class Developpeur { public int IdDeveloppeur { get; set; } public string Prenom { get; set; } public string Nom { get; set; } public string Email { get; set; } public string LangageFavori { get; set; } }

Pour effectuer le chargement des données, on peut utiliser des requêtes Linq :

Page 29: Présentation Windows 10 pour les développeurs - arati.fr · il change le modèle de distribution et de déploiement des ... adaptable testant la présence d'une fonctionnalité

29

public List<Developpeur> GetAllDeveloppeurs() { // utilisation de l’API WinRT Windows.Storage var chemin = System.IO.Path.Combine(Windows.Storage.ApplicationData.Current.LocalFolder.Path,

"developpeurs.db"); // création la base de données, si elle n'existe pas using (SQLite.Net.SQLiteConnection conn = new SQLite.Net.SQLiteConnection(

new SQLite.Net.Platform.WinRT.SQLitePlatformWinRT(), chemin)) { var query = from d in conn.Table<Developpeur>()

orderby d.IdDeveloppeur select d; return query.ToList(); } } En ce qui concerne Entity Framework 7, une approche similaire a été suivie (pour l’installation voir http://ef.readthedocs.org/en/latest/getting-started/uwp.html) dans le projet SQLiteEF7 :

Les entités définies y sont simplistes : public class Developpeur { [Key] public int IdDeveloppeur { get; set; } public string Prenom { get; set; } public string Nom { get; set; } public string Email { get; set; } public string LangageFavori { get; set; } public int LangageId { get; set; } public InfosLangage Langage { get; set; }

Page 30: Présentation Windows 10 pour les développeurs - arati.fr · il change le modèle de distribution et de déploiement des ... adaptable testant la présence d'une fonctionnalité

30

} public class InfosLangage { [Key] public int LangageId { get; set; } public string Nom { get; set; } public List<Developpeur> Developpeurs { get; set; } = new List<Developpeur>(); }

On y retrouve l’approche habituelle « code first » de EF6, avec la création d’une classe héritée de DBContext : class InfosLangageContext : DbContext { public DbSet<Developpeur> Developpeurs { get; set; } public DbSet<InfosLangage> Informations { get; set; } protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { string cheminDB = "InfosLangages.db"; try { // le chemin généré est quelque chose du style // "C:\Users\JM\AppData\Local\Packages\

// a3aaf87e-f4d3-48aa-aeb5-7522a36b09a0_4qenreemsht2t\LocalState" cheminDB = Path.Combine(ApplicationData.Current.LocalFolder.Path, cheminDB); } catch (InvalidOperationException) { } optionsBuilder.UseSqlite($"Data source={cheminDB}"); // chaine de connexion } } Les requêtes utilisent la syntaxe familière :

lvwDeveloppeurs.ItemsSource = db.Developpeurs.OrderBy(d => d.Prenom).ToList(); Comme dans l’exemple précédent, l’interface utilisateur est codée en XAML. L’affichage des développeurs est confié à un contrôle ListView (dans MainPage.xaml): … <ListView Name="lvwDeveloppeurs" Grid.Column="1" Grid.Row="5"> <ListView.ItemTemplate> <DataTemplate> <StackPanel Orientation="Horizontal" > <TextBlock Text="{Binding Prenom}" /> <TextBlock Text="{Binding Nom}" Margin="5,0,0,0" /> </StackPanel> </DataTemplate> </ListView.ItemTemplate> </ListView> …

Page 31: Présentation Windows 10 pour les développeurs - arati.fr · il change le modèle de distribution et de déploiement des ... adaptable testant la présence d'une fonctionnalité

31

Architecture : la « Microsoft Web Platform » Microsoft avait besoin d'un nouveau moteur de navigateur, car historiquement, Trident contenait une série de "compromis de compatibilité" avec le passé :

Afin de fabriquer un navigateur de haute performance il était nécessaire de :

conserver la compatibilité avec le passé, grâce à IE11

concentrer les nouveautés dans Edge, sans s'encombre de toutes les "rustines de compatibilité" d'IE 11.

Edge est un navigateur conforme aux standards HTML 5, et est compatible avec Firefox / Chrome etc. La chaine User-Agent reflète Edge. En plus de l'exécution d'application UWP HTML5/JavaScript téléchargées depuis le store et qui s'exécutent purement "off line", il est possible également d'avoir des "hosted apps", qui restent en ligne, et dont le contenu est donc toujours à jour :

Page 32: Présentation Windows 10 pour les développeurs - arati.fr · il change le modèle de distribution et de déploiement des ... adaptable testant la présence d'une fonctionnalité

32

Cette application "hébergée" peut savoir si elle est "online" ou "offline" et exécuter du code conditionnellement en fonction de cela. Elle a accès à l'API UWP. Pour construire une "hosted web app" on peut utiliser :

1. Visual Studio et créer une application universelle JavaScript, en retirer tout le contenu (sauf les images pour garder le ‘splashscreen’), et en modifier le manifeste pour le faire "pointer" vers le contenu Web et y définir quelle sont les API UWP que cette application pourra invoquer.

2. Manifoldjs (installé via node) et lui faire générer directement les apps pour toutes les plateformes (packagées éventuellement par Cordova pour iOS / Android).

Noter l'existence de Vorlonjs permettant de debugger à distance les applications crées ainsi. Le contrôle WebView est disponible pour les applications et utilise le moteur Edge. Il y a un contrôle WebView pour les applications XAML également, et le rendu visuel du WebView est effectué en dehors de l’UIThread. Une API (AddWebAllowedObject()) permet d'injecter des objets C#/C++ dans le WebView et de les rendre disponibles pour le script.

Pratique : applications HTML 5 Apache Cordova Projet exemple : jQMCordova, exécution sur l’ordinateur local et un Lumia 640 XL (Windows 10) :

Page 33: Présentation Windows 10 pour les développeurs - arati.fr · il change le modèle de distribution et de déploiement des ... adaptable testant la présence d'une fonctionnalité

33

Cet exemple, d’architecture « classique » est basé sur les Frameworks JQuery Mobile / JQuery et Apache Cordova. Sa particularité est d’être développée avec les « outils Cordova pour Visual Studio 2015 », qui sont désormais relativement au point et marquent la volonté de Microsoft d’attirer dans son environnement des développeurs de tous bord. Microsoft est un contributeur très actif du projet Apache Cordova (https://cordova.apache.org). L’interface utilisateur est codée en HTML5/CSS 3 et utilise jQuery Mobile pour améliorer son apparence « mobile ». Ainsi les « zones rétractables » sont de simples div codées ainsi : <div data-role="collapsible" id="infos">

<h3>Informations générales</h3>

<div id='aff_infos'>

</div>

</div>

et « habillées » avec le CSS de jQuery Mobile. Le rôle de Cordova est de fournir une API portable d’accès aux fonctionnalités de bas niveau du terminal, normalement inaccessibles pour les applications web. Cela est effectué par l’intermédiaire de « plugins » que l’on peut choisir d’ajouter au projet :

Le code est bien sûr écrit en JavaScript. Par exemple : …. // fonctions de gestion de la géolocalisation ///////////////////////////////////////////////////// var watchIDGeo = null; function startWatchGeoLoc() { var elementGeo = document.getElementById('aff_geo'); elementGeo.innerHTML = '<b>Ecoute en cours...</b> <p></p>'; watchIDGeo = navigator.geolocation.watchPosition( // en cas de succès function (position) { elementGeo.innerHTML = '<b>Latitude : </b>' + position.coords.latitude + '<br>' + '<b>Longitude: </b>' + position.coords.longitude

Page 34: Présentation Windows 10 pour les développeurs - arati.fr · il change le modèle de distribution et de déploiement des ... adaptable testant la présence d'une fonctionnalité

34

+ '<br>'; }, // en cas d'erreur function (erreur) { elementGeo.innerHTML = 'code: ' + erreur.code + '<br>' + 'message: ' + erreur.message + '<br>'; }, // comme option, un timeout de 30s { timeout: 30000, enableHighAccuracy: true }); } function stopWatchGeoLoc() { if (watchIDGeo) { navigator.geolocation.clearWatch(watchIDGeo); watchIDGeo = null; // pour une éventuelle reprise } } //// fin des fonctions de gestion de la géolocalisation })();

Page 35: Présentation Windows 10 pour les développeurs - arati.fr · il change le modèle de distribution et de déploiement des ... adaptable testant la présence d'une fonctionnalité

35

Architecture : UWP sur IOT ("Internet of Things") Tous les experts semblent d'accord : le marché des objets connectés est le prochain Eldorado. Microsoft entend donc bien profiter de la remise à plat de sa plate-forme pour figurer dans la liste des environnements compatibles avec les technologies IoT. Il a donc porté Windows 10 vers des environnements embarqués typiques : ceux basés sur les processeurs ARM et x86. Au fond des machines pour lesquelles il dispose déjà de compilateurs...

1 – Plateformes supportées

A l'heure actuelle (la liste peut fortement évoluer dans les mois/années à venir) les plateformes

supportées sont donc :

la plateforme ARM avec le Rasberry Pi 2 (mais PAS les modèles précédents), une carte à 35

euros extrêmement populaire et répandue, utilisant généralement un Linux embarqué

(Rasbian, Ubuntu, …) comme OS.

la plate-forme x86 (en déclinaison embarquée, avec un processeur Atom E38XX), avec la

carte MinnowBoard Max.

Pour le moment l'environnement Windows 10 est gratuit sur ces plateformes, mais assez différent

de ce que l'on trouve sur desktop (sur le RP 2, par exemple, il est "headless", c'est à dire qu'il ne

fournit pas de shell texte ou console embarquée, bien qu'il soit possible de l'administrer à distance

via une application Web).

On ne détaillera pas ici tous les aspects de l'installation / configuration de l'environnement

Windows 10 sur Rasberry Pi 2, un site y est consacré (https://dev.windows.com/fr-fr/iot) et les

détails en sont beaucoup trop nombreux.

Pour faciliter la mise en route, Microsoft (en collaboration avec Adafruit) propose même un kit de

démarrage comprenant un RP2, une carte micro-SD avec Windows 10 et peu de hardware (plaque

de prototypage, adaptateur Wifi etc.) pour une centaine d'euros...

2 – Modèle de programmation

Bien sûr, à l'heure actuelle, il n'existe pas de Visual Studio tournant sur plate-forme ARM, donc les applications seront développées sur un PC "contrôlant" un device connecté à travers le réseau. Le type de l'application à utiliser est simplement une application Windows universelle, à laquelle on a ajouté les extensions IoT :

Page 36: Présentation Windows 10 pour les développeurs - arati.fr · il change le modèle de distribution et de déploiement des ... adaptable testant la présence d'une fonctionnalité

36

Cet ajout permet d'accéder aux API Windows pour devices IoT permettant la programmation des périphériques du Rasberry Pi (il est à noter que cette application, étant couplée à une configuration hardware, n'a pas vocation à être portable !) :

On y note la présence des namespaces :

Windows.Devices.Adc : support de la conversion analogique / numérique (pour les cartes qui le possèdent).

Windows.Devices.Gpio : support des E/S numériques parallèles.

Windows.Devices.I2c : support du bus I2C.

Windows.Devices.Pwm : support de la modulation par largeur d'impulsions ("pulse width modulation").

Windows.Devices.Spi : support du protocole d'échange série à haute vitesse.

Page 37: Présentation Windows 10 pour les développeurs - arati.fr · il change le modèle de distribution et de déploiement des ... adaptable testant la présence d'une fonctionnalité

37

Pratique : exemple UWP sur Rasberry Pi 2

Projet exemple : RPCouleur

Cet exemple utilise une carte Rasberry Pi 2 couplée avec un capteur de couleur Adafruit (basé sur le circuit TCS 34725) à travers le bus I2C de la carte :

L'application (minimale…) tente de mesurer les 3 composantes de couleur d'échantillons et en identifier la couleur. Elle est développée en XAML / C# et utilise les extensions IoT : contrôle du bus GPIO ("General Purpose Input Output"), gestion du protocole I2C pour communiquer avec le TCS 34725. En voici l'apparence :

Page 38: Présentation Windows 10 pour les développeurs - arati.fr · il change le modèle de distribution et de déploiement des ... adaptable testant la présence d'une fonctionnalité

38

Il est possible, depuis Visual Studio 2015, de débugger confortablement l'application alors qu'elle s'exécute dans l'environnement embarqué. Il faut pour cela configurer l'environnement de débogage du projet en conséquence :

Page 39: Présentation Windows 10 pour les développeurs - arati.fr · il change le modèle de distribution et de déploiement des ... adaptable testant la présence d'une fonctionnalité

39

Autres évolutions Visual Studio 2015 Evolution des langages supportés par Visual Studio 2015 (C#, C++).

Evolution des outils de Visual Studio

Survols des nouveautés syntaxiques de C# 6

Projet exemple : CS6 Contrairement à C# 5, C# 6 n'amène pas de nouveautés révolutionnaires mais de nombreuses améliorations utiles. En voici un tour d'horizon rapide.

Using static

Il est désormais possible (comme en Java) d'effectuer des using static pour permettre l'utilisant directe, non préfixée de membres static de classes et de structures : using static System.Console; … WriteLine("Appel de WriteLine sans mentionner le nom de la classe");

Opérateurs conditionnels null

Cet opérateur (l'opérateur 'Elvis', voir image ci-dessus !) évite de tester si une référence est nulle avant de l'utiliser. On peut donc écrire : Personne p = null; // aucune erreur, affichage vide (null) WriteLine("Adresse : " + p?.Adresse);

Il est particulièrement utile lorsqu'il est chainé à travers plusieurs expressions, car il effectue un court-circuit d'évaluation : // l'opérateur de propagation de null peut être chainé // une invocation ne sera pas effectuée en cas de valeur nulle à gauche // (pas d'appel de Substring(), ici) string adresse1 = p?.Adresse?.Substring(0, 10); // il effectue un court circuit d'évaluation : pas d'appel de Substring() adresse1 = p?.Adresse.Substring(0, 10);

Il peut être utilisé conjointement à "l'opérateur de fusion null" ('null coalescing operator') ?? apparu dans une version précédente de C# : // affiche "Objet non instancié !" WriteLine("Adresse : " + (p?.Adresse ?? "Objet non instancié !")); Bien sûr, si la variable de stockage est une valeur, elle doit pouvoir être « nullable », puisque l'ensemble de l'expression pourra être null :

Page 40: Présentation Windows 10 pour les développeurs - arati.fr · il change le modèle de distribution et de déploiement des ... adaptable testant la présence d'une fonctionnalité

40

int? taille = p?.Adresse?.Length; if (taille.HasValue) WriteLine("La longueur est définie !");

Initialiseurs de propriétés automatiques et d'indexeurs

Il est depuis longtemps possible de créer des propriétés automatiques en C# : public string Adresse { get; set; } Il est désormais possible de les initialiser explicitement, lors de leur déclaration : // initialiseur de propriété automatique public string Nom { get; set; } = "Dupont";

Ou bien dans la définition du constructeur de la classe : public DateTime DateNaissance { get; } … // initialisation possible dans le constructeur public Personne() { DateNaissance = DateTime.Now; }

Cela fonctionne également avec les propriétés en lecture seule : public string Prenom { get; } = "Marc"; Depuis C# 3, on peut initialiser les listes ainsi :

// initialiseurs de propriétés et d'index List<string> liste = new List<string>() { "un", "deux", "trois"};

Cette syntaxe peut s'appliquer désormais à tous les indexeurs, comme ceux des dictionnaires :

// depuis C# 6 , fonctionne avec tout indexeur Dictionary<string, double> constantes = new Dictionary<string, double>() {["pi"] = 3.141592,["e"] = 2.71828 };

Interpolation de chaines

Une chaine littérale précédée par le caractère $ est appelée une 'chaine interpolée', et on peut y faire figurer des expressions entre une paire d'accolades (comme avec String.Format()) : WriteLine($"Premier élément : {liste[0]}, second : {liste[1]}"); Elle doit être sur une seule ligne à moins d'être une chaine 'verbatim' (précédée par le caractère @ pour interdire l'interprétation des caractères d'échappement) : string verbatim = $@"Le premier élément est : {liste[0]} et le second : {liste[1]}"; WriteLine(verbatim);

Page 41: Présentation Windows 10 pour les développeurs - arati.fr · il change le modèle de distribution et de déploiement des ... adaptable testant la présence d'une fonctionnalité

41

Cette syntaxe vise à simplifier et à rendre plus direct le formatage de chaines.

Filtres d'exceptions

Un filtre d'exception permet de n'intercepter un exception dans un bloc catch :

que si elle est d'un certain type (comme par le passé…)

et que si une de ses propriétés a une certaine valeur testée via l'opérateur when. Ex : try { LanceException(); } catch (MonException me) when (me.Code == 42) { WriteLine("Le code vaut 42 !"); } catch (MonException me) when (me.Code == 17) { WriteLine("Le code vaut 17 !"); }

La lancée de l'exception étant effectuée comme d'habitude, l'objet exception ayant une propriété Code spécifique, initialisée par le constructeur : private static void LanceException() { throw new MonException(17); }

Nouveautés diverses

Une nouveauté essentielle, mais de peu d'impact direct pour le développeur est que la chaine de compilation est désormais entièrement codé en C# (projet 'Roslyn') et Open Source (https://github.com/dotnet/roslyn). Cela va permettre de simplifier la création d'outils tiers s'interfaçant avec le compilateur. D'autre part, une limitation a été levée sur l'usage de await dans le contexte d'un bloc de traitement d'exceptions. Il est désormais possible d'appeler une méthode asynchrone avec await dans un bloc catch ou finally. Autre évolution de syntaxe : une méthode peut désormais être exprimée avec une syntaxe proche de celle des expressions lambda ("expression bodied methods") : // méthode retournant une chaine prenom + nom (expression bodied method") // syntaxe similaire à celle des expressions lambda string getInfos() => Prenom + " " + Nom;

Enfin, l'opérateur nameof permet désormais de retrouver le nom d'un symbole : // retrouve le nom d'un symbole (controlé en phase compilation) Personne p = null;

Page 42: Présentation Windows 10 pour les développeurs - arati.fr · il change le modèle de distribution et de déploiement des ... adaptable testant la présence d'une fonctionnalité

42

WriteLine(nameof(p.Adresse)); // affiche Adresse WriteLine(nameof(p) + "." + nameof(p.Adresse)); // affiche p.Adresse

Evolution de C++

C++, contrairement aux « langages maison » de Microsoft n’était pas, avant Visual Studio 2015 au niveau de la norme internationale ISO C++ 13. C’est maintenant quasiment chose faite, et certaines portions de C++ 17 sont déjà présentes. C’est une bonne nouvelle pour tous les développeurs C++ sous Windows.

Nouveaux outils de l’IDE

Il n’est pas possible d’évoquer ici toutes les nouveautés de Visual Studio, dans cette présentation avant tout consacrée à Windows 10. Evoquons cependant une série d’outils de débogage très élaborés comme :

L’outil d’examen de l’arborescence des composants XAML.

Un très riche outil de diagnostic

Etc.

Page 43: Présentation Windows 10 pour les développeurs - arati.fr · il change le modèle de distribution et de déploiement des ... adaptable testant la présence d'une fonctionnalité

43

Le modèle de distribution La distribution des applications UWP est désormais effectuée par la Windows Store qui unifie toutes les anciennes (Windows Phone, Windows Store, Xbox store etc.). De nombreuses optimisations techniques y ont également été ajoutées :

téléchargement intelligent : si un composant d'une application (Dll) est déjà installé, pas de doublon créé ("file single instancing").

Compilation native dans le cloud avant la distribution pour éviter le reverse engineering et maintenir un seul binaire de distribution.

"Applications masquées" pour permettre la distribution contrôlée à une petite audience.

Cibler la tarification par pays de distribution.

Evaluation temporaire.

Publication privée, à travers la "Business Store" (distribution sélective d'une nouvelle application ou choix pour une entreprise d'une série d'applications sélectionnées par un administrateur).

Avant la soumission de l'application, il est souhaitable d'utiliser le WACK ("Windows App Certification Kit") afin de voir les éventuels problèmes de l'application. Microsoft Advertising SDK permet d'insérer de la publicité dans ses applications sous formes de bannières, de "vidéos interstitielles" ("interstitial videos"). L'achat "in app" est également supporté.

Etapes pratiques

3. S'enregistrer comme développeur auprès du Windows Dev Center. Les frais d'inscription

annuels sont de 14 € pour un individuel et 75 € pour une entreprise. Le règlement permettra d'accéder à son tableau de bord de développeur (encore vide!) :

Page 44: Présentation Windows 10 pour les développeurs - arati.fr · il change le modèle de distribution et de déploiement des ... adaptable testant la présence d'une fonctionnalité

44

4. Réserver un nom pour la nouvelle application. Cela laisse 1 an pour effectivement soumettre l'application. Au-delà ; la réservation de ce nom sera caduque.

5. Soumettre l'application au store, après s'être assurée qu'elle est conforme aux règles énoncées à https://msdn.microsoft.com/fr-fr/library/windows/apps/hh694062.aspx.

Page 45: Présentation Windows 10 pour les développeurs - arati.fr · il change le modèle de distribution et de déploiement des ... adaptable testant la présence d'une fonctionnalité

45

Quelle stratégie pour le futur ? Compte tenu de l’ampleur des évolutions effectuées, Microsoft a pris un virage significatif qui devrait encourager les entreprises intéressées par la mobilité et les nouveaux devices, à explorer ces nouvelles voies. Il est bien sûr difficile de prévoir l’avenir exact de la plateforme UWP. Cependant :

On a pu constater qu’elle est bâtie sur des technologies pérennes et stables (XAML, .Net, HTML etc.)

Les technologies du passé restent valides et continuent d’évoluer.

Une ouverture importante est clairement constatée chez Microsoft (nouvelles plateformes supportées, ouverture du code source…). Cela va dans le sens de l’orientation constatée chez les autres grands éditeurs.

Les outils de développement (Visual Studio) déjà excellents, s’améliorent encore et une déclinaison gratuite, de qualité (la « community edition »), est enfin disponible (rappelons que ni Xcode ni Android Studio ne sont payants).

Il est donc probable que les développeurs apprécieront tout cela, mais bien sûr, c’est le marché qui va en décider l’adoption véritable : si la plateforme mobile de Micrsosoft décolle un tant soit peu, nul doute qu’UWP ait de beaux jours devant elle…

Page 46: Présentation Windows 10 pour les développeurs - arati.fr · il change le modèle de distribution et de déploiement des ... adaptable testant la présence d'une fonctionnalité

46

Annexe technique 1 - Utilisation d'une architecture MVVM Dans les exemples vus précédemment, on a essayé de garder une structure de projet aussi basique que possible, mais, dans la réalité, cette approche a de nombreux inconvénients :

mauvaise répartition des responsabilités

mauvais support de la séparation design / codage

mauvais support du test etc. Les applications UWP XAML, comme les applications WPF / Silverlight / WinRT Win 8.x gagneront à être structurées suivant le pattern MVVM, désormais ouvertement recommandé par Microsoft.

1 – Principes

Le pattern MVVM, qui est dérivé du pattern "Model Vue Contrôleur" est bien adapté aux applications XAML, car :

Comme les applications MVC, les applications MVVM séparent bien les responsabilités et simplifient la structuration de l'application, le travail en équipe et les rôles designers / codeurs. On y distingue le modèle de données, les vues pour les publier et interagir avec l'utilisateur et le "viewmodel" formant le contrôleur.

Comme les applications MVC, les applications MVVM sont plus faciles à tester qu'une application "code behind classique", puisque le routage des commandes via le "Viw Model" rend plus simple la simulation des interactions utilisateur, via des mocks, par exemple.

Contrairement à de nombreux Frameworks MVC, les applications XAML supporte le binding, simplifiant le couplage "lâche" entre les vues et le modèle de données. Le binding, et la propagation des notifications de modification des données. Typiquement, bien que cela ne soit pas obligatoire, une vue est couplée avec une classe de ViewModel (ou de PresentationModel) qui représente son DataContext de binding, connecté déclarativement dans le XAML (préférentiellement) ou bien par code.

Pour mettre en place une infrastructure MVVM, de la "plomberie" est cependant nécessaire :

les propriétés doivent être "observables", c'est à dire notifier à leur "abonnés" lorsque leur valeur est modifiée, à travers l'émission de l'événement PropertyChanged.

Les propriétés Command de certains contrôles XAML (les boutons par exemple) doivent être "connectées" à des méthodes de la classe ViewModel à travers une classe de commande implémentant l'interface ICommand.

Des convertisseurs de données sont souvent nécessaires (des classes implémentant l'interface IValueConverter).

2 – Exemple

Projet exemple : SplitViewApp1 Ce projet exemple a été généré par un template de projet SplitViewApp, issu de "10 ! Intense Templates" et a été conservé tel quel. Il possède une structure MVVM.

Page 47: Présentation Windows 10 pour les développeurs - arati.fr · il change le modèle de distribution et de déploiement des ... adaptable testant la présence d'une fonctionnalité

47

Dans ce projet, la vue principale, un UserControl, est appelée Shell et possède une propriété ViewModel de typer ShellViewModel. Ce ViewModel connecté / bindé à Shell.xaml, publie les propriétés et commandes suivantes :

IsSplitViewPaneOpen (propriété) : bindée à la propriété IsPaneOpen de la SplitView.

ToggleSplitViewPaneCommand (commande) : connectée à la propriété Command du bouton "hamburger" et produisant le toggle de la propriété précédente.

MenuItems (propriété) : bindée à la propriété ItemSource de la ListView, affichée dans le SplitView.Pane et présentant les options de menu.

SelectetedMenuItem (propriété) : bindée à la propriété SelectedItem de la ListView. Pour permettre la navigation avec un bouton Back et un historique de navigation, le SplitView.Content contient un Frame, dont la propriété SourcePageType (type de la page vers laquelle naviguer) est bindée à la propriété SelectedPageType du ViewModel. Enfin, pour présenter dans la ListView les boutons de navigation un DataTemplate, publiant chaque MenuItem permet de retrouver l'icône et l'intitulé de chaque option, affichés dans 2 TextBlocks.

Page 48: Présentation Windows 10 pour les développeurs - arati.fr · il change le modèle de distribution et de déploiement des ... adaptable testant la présence d'une fonctionnalité

48

3 – Utilisation d'un framework MVVM

Plutôt que d'implémenter "à la main" toute cette plomberie, on peut alternativement utiliser un framework MVVM comme MVVMLight de Laurent Brugnon, qui d'ores et déjà supporte les applications UWP (version 5.2 et plus).

On pourra examiner profitablement un projet minimal UWP implémenté à travers MVVMLight.

Page 49: Présentation Windows 10 pour les développeurs - arati.fr · il change le modèle de distribution et de déploiement des ... adaptable testant la présence d'une fonctionnalité

49

Annexe technique 2 – programmation asynchrone La programmation asynchrone est tellement importante dans l'environnement UWP qu'il nous a semblé important d'en rappeler les grands principes et quelques détails de mise en œuvre.

1 - Principes et concepts généraux

Un traitement synchrone effectue son travail avant de repasser le contrôle à son code appelant. Inversement, un traitement asynchrone effectue la plupart de son travail après avoir repassé le contrôle à son code appelant. Si la traitement demandé nécessite la création d'un nouveau thread, car il doit s'exécuter en parallèle du traitement principal, (typiquement une tâche utilisant intensivement le CPU, comme de la compression de données, des calculs mathématiques intensifs etc.) ce thrad sera créé et mis à disposition du traitement asynchrone. Si le traitement ne nécessite pas la création d'un nouveau thread, car il s'agit principalement d'attendre un périphérique plus lent et donc d'éviter d'être "coincé" dans cette attente, un second thread ne sera pas créé et l'appelant ne sera pas non plus bloqué dans cette attente grâce à un mécanisme de callback. On distingue donc fréquemment ces deux scenarii asynchrones : "CPU bound" (avec création de thread pour exécuter des traitements CPU lourds), et "I/O bound" (pour simplement attendre un périphérique lent, sans création de nouveau thread). Il est donc essentiel de ne pas associer systématiquement comportement asynchrone et threading. Lorsque l'on souhaite utiliser des threads avec des traitements asynchrones, on le fait généralement par l'intermédiaire d'une tâche (une instance de la classe Task<T>), qui fournit de nombreux mécanismes pour manipuler souplement le thread créé (possibilité d'indication de progression, d'annulation, de continuation etc.). Lorsque l'on met directement en jeu des threads (qu'ils soient ou non dans le ThreadPool), c'est souvent l'appelant qui va le créer et tout l'arbre des appels du traitement de fond sera dans le contexte de ce thread avec tous les problèmes habituels qui y sont liés (synchronisation, communication inter-threads etc.). Cette approche est souvent appelée threading à "granularité large". Lorsque l'on utilise des Tasks, la création du thread sera faite juste au moment nécessaire, et la plupart des appels de l'arbre des appels du traitement de fond seront dans le contexte du thread appelant (threading à "granularité fine"). Les avantages de la programmation asynchrone sont tellement importants qu'elle est devenu un passage obligé dans de nombreux langages et cas de figure :

en JavaScript, avec node js, où ce modèle a été popularisé (programmation monothread asynchrone d'applications serveur).

Avec WinRT et UWP où chaque traitement de plus de 50 ms possède une API d'appel asynchrone.

Etc. etc.

Page 50: Présentation Windows 10 pour les développeurs - arati.fr · il change le modèle de distribution et de déploiement des ... adaptable testant la présence d'une fonctionnalité

50

2 - Threads et tâches

Projet exemple : AsyncBase Dans ce projet on expose les étapes de passage de l'utilisation du threading 'classique' à l'approche asynchrone en utilisant les classes Task<T>, TaskAwaiter<T> et TaskCompletionSource<T>.

Plutôt que de créer directement des threads on commencera par passer par la méthode Task.Run() ainsi (les lambdas fournissent un moyen commode de définir le code utile du nouveau thread) :

Task tache = Task.Run(() => { WriteLine("Démarrage de la tâche..."); Thread.Sleep(2000); WriteLine("Après l'appel de Thread.Sleep()..."); });

Depuis le thread principal il est aisé de savoir si la tâche est effectivement terminée, via la propriété IsCompleted :

// lorsque l'on arrive ici, la tâche précédente n'est pas finie WriteLine($"Avant Wait(), tâche terminée : {tache.IsCompleted}");// False

Il est possible d'attendre la fin de l'exécution d'une tâche via l'appel de Wait() (comportement similaire à Join() sur un Thread) : tache.Wait(); // bloqué ici, tant que la tâche n'a pas fini WriteLine($"Après Wait(), tâche terminée : {tache.IsCompleted}"); // True

Il est problématique, pour la bonne gestion de la montée en charge de l'application que plusieurs threads du pool soient bloquées, et on peut donc également créer des tâches associées à des threads qui ne sont pas dans le pool de threads (option 'LongRunning') : tache = Task.Factory.StartNew(() => { WriteLine("Démarrage de la tâche..."); Thread.Sleep(2000); WriteLine("Après l'appel de Thread.Sleep(), LongRunning..."); // garantit le "surabonnement" (+ de threads que de coeurs dispos). }, TaskCreationOptions.LongRunning);

Les problèmes principaux des threads de bas niveau sont :

Qu'il n'est pas très aisé de leur passer des paramètres et de leur faire retourner un résultat, à moins de mettre en œuvre du partage de données, avec les problèmes habituels que cela pose (synchronisation).

Qu'ils ne propagent pas les exceptions. Dans le cas d'une exception déclenchée dans le code d'un thread de background, le thread principal n'en sera pas notifié et le gestionnaire d'exception devra donc se trouver dans le code du thread lui-même. Ce comportement est souhaitable si le code du thread est complètement indépendant du code du thread

Page 51: Présentation Windows 10 pour les développeurs - arati.fr · il change le modèle de distribution et de déploiement des ... adaptable testant la présence d'une fonctionnalité

51

principal, mais PAS s'il exécute du code subordonné et associé au code du thread principal (thread 'tâcheron').

Ces deux problèmes sont aisément résolus grâce aux taches. Ainsi, la classe Task étant générique, on pourra retrouver un résultat typé d'exécution : Task<int> maTache = Task.Run(() => { WriteLine("Affichage inutile");

return 19; });

int resultat = maTache.Result; // appel bloquant si pas terminé WriteLine($"Le résultat est {resultat}."); // 19 En ce qui concerne la gestion des exceptions, les tâches les propageront à l'occasion de l'attente de la fin de la tâche de background (appel de Wait()) où de la lecture du résultat (lecture de la propriété Result) : // La gestion des exceptions avec les threads est notoirement complexe // et oblige généralement à créer des blocs try... catch dans le code des // threads elles mêmes. // Avec les Tasks, le problème est bien plus simple : elles propagent les // exceptions au code qui appelle Wait() ou lit la valeur Result.

// lève une NullReferenceException Task uneTache = Task.Run(() => { throw null; }); try { // l'exception "remonte" du fait de cet appel et est "embarquée" // dans une AggregateException uneTache.Wait(); } catch (AggregateException aex) { if (aex.InnerException is NullReferenceException) WriteLine("NullReferenceException interceptée !"); else throw; }

3 - Continuations

Projet exemple : AsyncBase Il est fréquent que l'on 'compose' des tâches élémentaires pour construire un traitement complexe. Pour cela il est nécessaire qu'à la fin d'une tâche, une nouvelle puisse être démarrée, typiquement via une continuation. La première façon de procéder est d'attendre la fin d'une tâche avec un TaskAwaiter et de lancer un traitement via un callback : // un TaskAwaiter permet d'attendre la fin d'une tâche et d'invoquer // alors un callback. // Il permet donc d'effectuer une exécution chainée à la fin d'une tâche // ("continuation") Task<int> tacheTriviale = Task.Run(() =>

Page 52: Présentation Windows 10 pour les développeurs - arati.fr · il change le modèle de distribution et de déploiement des ... adaptable testant la présence d'une fonctionnalité

52

{ Thread.Sleep(2000); return 10; }); TaskAwaiter<int> awaiter = tacheTriviale.GetAwaiter(); // le gestionnaire événement et la lambda de callback awaiter.OnCompleted(() => { WriteLine($"Bien fini ? : {awaiter.IsCompleted}"); // true // Affiche le résultat WriteLine($"Résultat dans OnCompleted : {awaiter.GetResult()}"); });

Une seconde technique est d'utiliser la méthode ContinueWith() de Task<T> qui permet d'effectuer directement la continuation : Task<int> autreTacheTriviale = Task.Run(() => { Thread.Sleep(2000); return 20; });

Task<int> secondeTache = autreTacheTriviale.ContinueWith( tachePrecedante => { int resultat = tachePrecedante.Result; WriteLine($"Résultat de autreTacheTriviale : {resultat}"); return resultat; });

Enfin la classe TaskCompletionSource permet de créer et manipuler aisément un objet Task, avec, optionnellement, un thread associé : var awaiter2 = temporisation1(2000).GetAwaiter(); awaiter2.OnCompleted( () => WriteLine( $"Résultat retourné par temporisation1() : {awaiter2.GetResult()}")); // utilisation d'une fonction générale de temporisation codée ainsi temporisation2(2000).GetAwaiter().OnCompleted( () => WriteLine("Fin de l'appel de temporisation2(), après 2 s."));

// ou plus simplement... Task.Delay(2000).GetAwaiter().OnCompleted( () => WriteLine("Fin de l'appel de Task.Delay(), après 2 s.") );

// méthode asynchrone, sans support de syntaxe static Task<int> temporisation1(int ms) { var tcs = new TaskCompletionSource<int>(); var timer = new System.Timers.Timer(ms) { AutoReset = false }; timer.Elapsed += delegate { timer.Dispose(); tcs.SetResult(10); }; timer.Start(); return tcs.Task; }

Page 53: Présentation Windows 10 pour les développeurs - arati.fr · il change le modèle de distribution et de déploiement des ... adaptable testant la présence d'une fonctionnalité

53

// méthode asynchrone, sans support de syntaxe static Task temporisation2(int ms) { var tcs = new TaskCompletionSource<object>(); var timer = new System.Timers.Timer(ms) { AutoReset = false }; timer.Elapsed += delegate { timer.Dispose(); tcs.SetResult(null); }; timer.Start(); return tcs.Task; }

4 - Les mots clés async et await

Projet exemple : AsyncBase Les tâches sont très pratiques pour créer des méthodes asynchrones. Mais lorsqu'on les lance il est difficile de garantir un ordre d'exécution prévisible, à moins de bloquer le thread principal qui doit attendre la fin de l'exécution de la première, avant de lancer la seconde et ainsi de suite. Une autre solution, non bloquante est d'utiliser les nouveaux mots clés await et async. L'instruction await crée en fait un "awaiter" et génère un callback qui sera invoqué automatiquement à la fin de la tâche concerné. Le mot clé async sert à marquer les méthodes qui utilisent await. On commence donc par créer une méthode asynchrone (noter le format et le nommage de la méthode) : static Task<int> FaitQQuechoseAsync() { return Task.Run(() => { WriteLine("Démarrage de la tâche de FaitQQuechoseAsync..."); Thread.Sleep(2000); WriteLine("Après l'appel de Thread.Sleep()..."); return 10; }); } Et le code qui l'appelle : static async void MiniAsynchrone() { int r = await FaitQQuechoseAsync(); WriteLine($"Après l'appel de FaitQQueChoseAsync, r = {r}"); }

En fait le mot clé await signifie que l'appel de FaitQQuechoseAsync() retourne immédiatement, mais que le code qui le suit (le WriteLine()) n'est exécuté qu'après que la méthode asynchrone ait fini son traitement. On a donc bien :

un appel asynchrone, non bloquant.

La garantie que ce qui suit cet appel dans la méthode, ne sera pas exécuté tant que la méthode asynchrone appelée n'aura pas fini son traitement, pour pouvoir chainer une

Page 54: Présentation Windows 10 pour les développeurs - arati.fr · il change le modèle de distribution et de déploiement des ... adaptable testant la présence d'une fonctionnalité

54

séquence de façon déterministe.

5 – Examen d'un cas d'école : téléchargements asynchrones

Projets exemples : Async1, Async2, Async3 Ces trois projets (des "micros applications" WPF "cas d'école") illustrent simplement l'utilisation de la programmation asynchrone pour télécharger des 'favicons' depuis des sites bien connus de l'Internet : private static readonly List<string> ListeDomaines = new List<string> { "google.com", "bing.com", "baidu.com", "oreilly.com", "microsoft.com", "facebook.com", "twitter.com", "lemonde.fr", "leboncoin.fr" }; Une fois téléchargées ces icônes sont affichées dans la zone cliente de la fenêtre principale :

La première version "bloque" le UI thread (ce qui est bien sûr une très mauvaise pratique…) lors du téléchargement, en rendant l'application un peu "saccadée" : private void OnClick(object sender, RoutedEventArgs e) { foreach (string domaine in ListeDomaines) { AjouteIcone(domaine); } } private void AjouteIcone(string domaine) { WebClient clientWeb = new WebClient(); // ligne suivante : appel bloquant byte[] bytes = clientWeb.DownloadData("http://" + domaine

Page 55: Présentation Windows 10 pour les développeurs - arati.fr · il change le modèle de distribution et de déploiement des ... adaptable testant la présence d'une fonctionnalité

55

+ "/favicon.ico"); Image controleImage = GenControleImage(bytes); Panel_Favicons.Children.Add(controleImage); }

private Image GenControleImage(byte[] bytes) { Image ctrl = new Image(); BitmapImage bitmapImage = new BitmapImage(); bitmapImage.BeginInit(); bitmapImage.StreamSource = new MemoryStream(bytes); bitmapImage.EndInit(); ctrl.Source = bitmapImage; ctrl.Width = 16; ctrl.Height = 16; return ctrl; } La seconde version remédie à cela en utilisant une approche plus avancée : elle utilise une version asynchrone de DownloadData() et en enregistrant un callback destiné à traiter les données téléchargées, lorsqu’elles sont disponibles. On obtient donc : private void OnClick(object sender, RoutedEventArgs e) { foreach (string domaine in ListeDomaines) { AjouteIcone(domaine); } } private void AjouteIcone(string domaine) { WebClient clientWeb = new WebClient(); clientWeb.DownloadDataCompleted += OnWebClientOnDownloadDataCompleted; clientWeb.DownloadDataAsync(new Uri("http://" + domaine + "/favicon.ico"));

// byte[] bytes = clientWeb.DownloadData("http://" + domaine // + "/favicon.ico"); }

private void OnWebClientOnDownloadDataCompleted(object sender, DownloadDataCompletedEventArgs args) { Image controleImage = GenControleImage(args.Result); Panel_Favicons.Children.Add(controleImage); }

private Image GenControleImage(byte[] bytes) { Image ctrl = new Image(); BitmapImage bitmapImage = new BitmapImage(); bitmapImage.BeginInit();

Page 56: Présentation Windows 10 pour les développeurs - arati.fr · il change le modèle de distribution et de déploiement des ... adaptable testant la présence d'une fonctionnalité

56

bitmapImage.StreamSource = new MemoryStream(bytes); bitmapImage.EndInit(); ctrl.Source = bitmapImage; ctrl.Width = 16; ctrl.Height = 16; return ctrl; }

La troisième version utilise async / await, ce qui élimine la nécessiter de définir un callback, et le code est affectivement asynchrone, mais avec la même lisibilité que du code synchrone :

private void OnClick(object sender, RoutedEventArgs e) { foreach (string domaine in ListeDomaines) { AjouteIcone(domaine); } } private async void AjouteIcone(string domaine) { WebClient clientWeb = new WebClient(); byte[] bytes = await

clientWeb.DownloadDataTaskAsync("http://" + domaine + "/favicon.ico"); Image controleImage = GenControleImage(bytes); Panel_Favicons.Children.Add(controleImage); } private Image GenControleImage(byte[] bytes) { Image ctrl = new Image(); BitmapImage bitmapImage = new BitmapImage(); bitmapImage.BeginInit(); bitmapImage.StreamSource = new MemoryStream(bytes); bitmapImage.EndInit(); ctrl.Source = bitmapImage; ctrl.Width = 16; ctrl.Height = 16; return ctrl; }

La ligne suivant await n'est exécutée que lorsque les données sont bien disponibles, supprimant donc la nécessité de définir un callback. On voit donc que ces deux mots clé rendent la programmation asynchrone bien plus lisible et simple à comprendre et à maintenir. Ils nécessitent par contre que les méthodes invoquées suivent le pattern asynchrone examiné précédemment.