C Sharp Mai 2009

  • Upload
    amongee

  • View
    64

  • Download
    4

Embed Size (px)

Citation preview

INUQUA(Institut Universitaire Quisqueya Amrique)

C Sharp 2008-2009Cliquez pour dbuterProf: Charles Jean Robelkend 1

Prof: Charles Jean RobelkendAnalyste, programmeur Phone: 3461-8514 Courriel: [email protected] Site: http://membres.lycos.fr/robelkend1

Prof: Charles Jean Robelkend

2

Installation et configuration

Plan Sommaire du Cours

Prof: Charles Jean Robelkend

3

1 : Interfaces Graphiques 2 : Evnements utilisateur 3 : Architectures 3 couches, tests unitaires Nunit.4 : Accs aux base de donnes 5 : Threads d'excution 6 : Programmation Internet 7 : Services Web

Plan

Prof: Charles Jean Robelkend

4

1 : Interfaces graphiques1.1 Les bases des interfaces graphiques 1.1.1 Une fentre simple 1.1.2 Un formulaire avec bouton 1.2 Quelques composants utiles 1.2.1 Formulaire Form 1.2.2 Etiquettes label et boites de saisie Textbox

Plan

Prof: Charles Jean Robelkend

5

1 : Interfaces graphiques(Suite)1.2.3 Listes droulantes Combobox 1.2.4 Composant Listbox 1.2.5 Cases cocher CheckBox, boutons radio ButtonRadio 1.2.6 Variateurs Scrollbar 1.6 vnements souris 1.7 Crer une fentre avec menu 1.7 Composants non visuels 1.7.1 Boites de dialogue OpenfileDialog et SavefileDialog 1.7.2 Boites de dialogue FontColor et ColorDialog 1.7.3 TimerProf: Charles Jean Robelkend 6

Plan

1 : Interfaces graphiques Nous nous proposons ici de montrer comment construire des interfaces graphiques avec C#. Nous voyons tout d'abord quelles sont les classes de base de la plate-forme .NET qui nous permettent de construire une interface graphique.

Prof: Charles Jean Robelkend

7

1 : Interfaces graphiques1.1 Les bases des interfaces graphiques Une interface graphique drive en gnral de la classe de base System.Windows.Forms.Form. La classe de base Form dfinit une fentre de base avec des boutons de fermeture, agrandissement/rduction, une taille ajustable, ... et gre les vnements sur ces objets graphiques.Prof: Charles Jean Robelkend 8

1 : Interfaces graphiques1.2 Un formulaire avec bouton Ecrire un programme en C Sharp affichant une fentre ayant en son centre un bouton.

Prof: Charles Jean Robelkend

9

Bases de linterface graphiques Les applications avec formulaires utilisent l'espace de noms System.Windows.Forms.

l'excution dun projet, la mthode [Main] est excute.

Prof: Charles Jean Robelkend

10

Bases de linterface graphiques la classe Application appartient l'espace de noms System.Windows.Forms. Elle contient des mthodes statiques pour lancer / arrter les applications graphiques windows.

Prof: Charles Jean Robelkend

11

Bases de linterface graphiquesLa methode Run de la classe Application instancie la classe [Form1] qui est la classe du formulaire et lui demande de s'excuter.

Prof: Charles Jean Robelkend

12

Ecrire les codes dune classe dans plusieurs fichiersOn utilise le mot cl partial pour indiquer quune classe est partielle et qu'elle peut tre complte par d'autres fichiers source. Nb. Les fichiers doivent tre compiles ensemble la facon suivante:csc [/r:library fichier.dll] fichier1.cs [fichier2.cs]Prof: Charles Jean Robelkend 13

1 : Interfaces graphiques1.4 Quelques composants utiles Nous prsentons maintenant diverses applications mettant en jeu les composants les plus courants afin de dcouvrir les principales mthodes et proprits de ceux-ci. Pour chaque application, nous prsentons l'interface graphique et le code intressant, principalement celui des gestionnaires d'vnements.Prof: Charles Jean Robelkend 14

1 : Interfaces graphiques1.4 Quelques composants utiles1.2 Quelques composants utiles 1.2.1 Formulaire Form Nous commenons par prsenter le composant indispensable, le formulaire sur lequel on dpose des composants. Nous avons dj prsent quelques-unes de ses proprits de base. Nous nous attardons ici sur quelques vnements importants d'un formulaire.

Prof: Charles Jean Robelkend

15

1 : Interfaces graphiquesLoad le formulaire est en cours de chargement Closed le formulaire est ferm L'vnement Load se produit avant mme que le formulaire ne soit affich. L'vnement Closing se produit lorsque le formulaire est en cours de fermeture. On peut encore arrter cette fermeture par programmation.

Prof: Charles Jean Robelkend

16

1 : Interfaces graphiques1.2.2 Listes droulantes ComboBoxUn composant ComboBox est une liste droulante double d'une zone de saisie : l'utilisateur peut soit choisir un lment dans (2) soit taper du texte dans (1).

Prof: Charles Jean Robelkend

17

1 : Interfaces graphiques1.2.2 Listes droulantes ComboBoxIl existe trois sortes de ComboBox fixes par la proprit DropDownStyle :

Prof: Charles Jean Robelkend

18

1 : Interfaces graphiques1.2.2 Listes droulantes ComboBoxSimple : liste non droulante avec zone d'dition DropDown : liste droulante avec zone d'dition DropDownList : liste droulante sans zone d'dition Exemple : comboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyl e.DropDownList;Prof: Charles Jean Robelkend 19

1 : Interfaces graphiquesPar dfaut, le type d'un ComboBox est DropDown. La classe ComboBox a un seul constructeur : new ComboBox() cre un combo vide Les lments du ComboBox sont disponibles dans la proprit Items : public ComboBox.ObjectCollection Items {get;} C'est une proprit indexe, Items[i] dsignant l'lment i du Combo. Elle est en lecture seule. Soit C un combo et C.Items sa liste d'lments. On a les proprits suivantes :Prof: Charles Jean Robelkend 20

1 : Interfaces graphiques(Combo)Quelques proprits de ComboBoxC.Items.Count nombre d'lments du combo C.Items[i] lment i du combo C.Add(object o) ajoute l'objet o en dernier lment du combo C.AddRange(object[] objets) ajoute un tableau d'objets en fin de combo C.Insert(int i, object o) ajoute l'objet o en position i du combo

Prof: Charles Jean Robelkend

21

1 : Interfaces graphiques(Combo)Quelques proprits de ComboBoxC.RemoveAt(int i) enlve l'lment i du combo C.Remove(object o) enlve l'objet o du combo C.Clear() supprime tous les lments du combo C.IndexOf(object o) rend la position i de l'objet o dans le combo C.SelectedIndex index de l'lment slectionn C.SelectedItem lment slectionn C.SelectedItem.Text texte affich de l'lment slectionn C.Text texte affich de l'lment slectionnProf: Charles Jean Robelkend 22

1 : Interfaces graphiques(Combo)Quelques proprits de ComboBoxOn peut s'tonner qu'un combo puisse contenir des objets alors que visuellement il affiche des chanes de caractres. Si un ComboBox contient un objet obj, il affiche la chane obj.ToString(). On se rappelle que tout objet a une mthode ToString hrite de la classe object et qui rend une chane de caractres "reprsentative" de l'objet.

Prof: Charles Jean Robelkend

23

1 : Interfaces graphiques(Combo)Evnement principalLors du choix d'un lment dans la liste droulante se produit l'vnement SelectedIndexChanged qui peut tre alors utilis pour tre averti du changement de slection dans le combo. Dans l'application suivante, nous utilisons cet vnement pour afficher l'lment qui a t slectionn dans la liste.

Prof: Charles Jean Robelkend

24

1 : Interfaces graphiques(ListBox)Les composants ListBox ont un mode de slection de leurs lments qui est dfini par leur proprit SelectionMode: One : un seul lment peut tre slectionn

Prof: Charles Jean Robelkend

25

1 : Interfaces graphiques(ListBox)MultiExtended: multi-slection possible : maintenir appuye la touche SHIFT et cliquer sur un lment tend la slection de l'lment rcdemment slectionn l'lment courant. MultiSimple: multi-slection possible : un lment est slectionn / dslectionn par un clic de souris ou par appui sur la barre d'espace.Prof: Charles Jean Robelkend 26

Case a cocher, boutons radioLe container GroupBox est un conteneur de composants, il permet de regrouper les boutons radio et les cases a cocher . On peut y dposer d'autres composants. Exemple GroupBox box = new GroupBox(); Box.add(radio1); Box.add(radio2);Prof: Charles Jean Robelkend 27

Case a cocher, boutons radioEvnement principalL'vnement principal pour ces contrles est l'vnement CheckChanged indiquant que l'tat de la case cocher ou du bouton radio a chang.

Prof: Charles Jean Robelkend

28

Variateurs ScrollBarUn variateur ScrollBar permet l'utilisateur de choisir une valeur dans une plage de valeurs entires symbolise par la "bande" du variateur sur laquelle se dplace un curseur. La valeur du variateur est disponible dans sa proprit Value.

Prof: Charles Jean Robelkend

29

Variateurs ScrollBarCes valeurs sont reprsentes par les proprits Minimum et Maximum et valent respectivement par dfaut 0 et 100.

Prof: Charles Jean Robelkend

30

Variateurs ScrollBar Lorsqu'on clique sur l'extrmit suprieure d'un variateur vertical, sa valeur diminue. Cela peut surprendre l'utilisateur moyen qui s'attend normalement voir la valeur "monter". On rgle ce problme en donnant une valeur ngative aux proprits SmallChange et LargeChange

Prof: Charles Jean Robelkend

31

Variateurs ScrollBar Ces cinq proprits (Value, Minimum, Maximum, SmallChange, LargeChange) sont accessibles en lecture et criture.

Prof: Charles Jean Robelkend

32

Variateurs ScrollBarEvnement principal L'vnement principal du variateur est celui qui signale un changement de valeur : l'vnement Scroll.

Prof: Charles Jean Robelkend

33

Variateurs ScrollBarUn composant NumericUpDown est proche du variateur : il a lui aussi les proprits Minimum, Maximum et Value, par dfaut 0, 100, 0. Mais ici, la proprit Value est affiche dans une bote de saisie faisant partie intgrante du contrle. L'utilisateur peut lui mme modifier cette valeur sauf si on a mis la proprit ReadOnly du contrle vrai. La valeur de l'incrment est fixe par la proprit Increment, par dfaut 1. L'vnement principal du composant NumericUpDown est celui qui signale un changement de valeur : l'vnement ValueChanged

Prof: Charles Jean Robelkend

34

vnements UtilisateursI. Introduction II. Crer votre vnement l'aide de la classe EventArgs III. Gnrer un vnement A. Le type delegate B. Le type event C. Gnrer l'vnement IV. Rcuprer un vnement dans un gestionnaire d'venmentsProf: Charles Jean Robelkend 35

I. IntroductionJe pense que presque tout le monde connat les vnements. A chaque fois que vous cliquez sur un bouton dans une application Windows vous dclenchez un vnement. Ici, le but est de crer des vnements qui vont tre propres votre application. C'est--dire dclencher une action dans votre application lorsque quelque chose se produit et informer les objets abonns cet vnement.Prof: Charles Jean Robelkend 36

II. Crer votre vnement l'aide de la classe EventArgsLa classe EventArgs est la classe de base pour crer vos vnements. A chaque fois que vous voulez crer un vnement, il vous faut driver une classe de EventArgs. Membres de la classe EventArgs :Prof: Charles Jean Robelkend 37

II. Crer votre vnement l'aide de la classe EventArgsConstructeurs publics Nom Definition EventArgs, constructeur. Initialise une nouvelle instance de la classe EventArgs.

Prof: Charles Jean Robelkend

38

II. Crer votre vnement l'aide de la classe EventArgsChamps publics Nom Definition Equals Surcharg. Dtermine si deux instances de Object sont gales.

Prof: Charles Jean Robelkend

39

II. Crer votre vnement l'aide de la classe EventArgsMthodes publiques Nom Definition EventArgs, constructeur Pris en charge par le .NET Compact Framework. Initialise une nouvelle instance de la classe EventArgs. GetHashCode (hrit de Object)Prof: Charles Jean Robelkend 40

II. Crer votre vnement l'aide de la classe EventArgsSert de fonction de hachage pour un type particulier, adapt une utilisation dans des algorithmes de hachage et des structures de donnes telles qu'une table de hachage. GetType (hrit de Object)

Prof: Charles Jean Robelkend

41

II. Crer votre vnement l'aide de la classe EventArgsGetType (hrit de Object) Pris en charge par le .NET Compact Framework. Obtient le Type de l'instance en cours. ToString (hrit de Object) Retourne un objet String qui reprsente l' Object en cours.Prof: Charles Jean Robelkend 42

II. Crer votre vnement l'aide de la classe EventArgsusing System; namespace TutoEvent { /// /// A la responsabilit de contenir le text de l'venement et de le rendre accessible /// public class GenerateTextEventArgs : EventArgs { private string myEventText = null; public GenerateTextArgs(string theEventText) { if (theEventText == null) throw new NullReferenceException(); myEventText = theEventText; } public string EventText { get { return this.myEventText; } } } Prof: Charles Jean Robelkend }

43

III. Gnrer un vnementA. Le type delegate Il n'est pas possible de parler des vnements sans parler des delegate. Un delegate est un objet qui permet d'appeler une fonction ou une srie de fonction. Un delegate est similaire aux pointeurs de fonctions du C/C++.

Prof: Charles Jean Robelkend

44

III. Gnrer un vnementA. Le type delegate Une variable delegate va permettre d'excuter une fonction ou plusieurs fonctions. Pour cela le delegate va stocker des rfrences sur des mthodes (que nous appellerons un gestionnaire d'venments ("Event handler")).

Prof: Charles Jean Robelkend

45

III. Gnrer un vnementA. Le type delegate La signature des mthodes rfrences devra respecter les rgles suivantes : - retourner void - prendre comme premier paramtre un type object que nous appellerons gnralement sender

Prof: Charles Jean Robelkend

46

III. Gnrer un vnementA. Le type delegate - prendre comme second paramtre un objet hritant de EventArgs, donc dans notre cas un objet GenerateTextEventArgs. Note : il est possible de voir des delegate dclarer autrement. Ici je montre simplement la mthode gnralement utilise pour les vnements.Prof: Charles Jean Robelkend 47

III. Gnrer un vnementA. Le type delegate Pour dclarer un delegate, nous utilisons la syntaxe suivante : public delegate void TextGeneratedEventHandler (object sender, GenerateTextEventArgs e);

Prof: Charles Jean Robelkend

48

III. Gnrer un vnementB. Le type event Il nous faut ensuite dclarer un objet event du type du delegate dclar plus haut. Le mot cl event vous permet de spcifier un dlgu appeler lors de l'occurrence d'un certain vnement dans votre code.

Prof: Charles Jean Robelkend

49

III. Gnrer un vnementB. Le type event Pour dclarer un event, nous utilisons la syntaxe suivante : public event TextGeneratedEventHandler OnTextChanged;

Prof: Charles Jean Robelkend

50

III. Gnrer un vnementC. Gnrer l'vnement Pour gnrer un vnement il suffit d'appeler son constructeur avec les paramtres ventuels comme ceci : GenerateTextEventArgs e = new GenerateTextEventArgs("Compteur = " + i.ToString());

Prof: Charles Jean Robelkend

51

III. Gnrer un vnementPuis il nous reste envoyer cet vnement tout le monde :if (e != null) OnTextChanged(this,e);

Prof: Charles Jean Robelkend

52

IV. Rcuprer un vnement dans un gestionnaire d'venmentsUn gestionnaire d'venments ("Event Handler") est la mthode qui va s'excuter en rponse l'vnement. Un Event hanlder retourne normalement void et accepte 2 paramtres qui sont :

Prof: Charles Jean Robelkend

53

IV. Rcuprer un vnement dans un gestionnaire d'venments- le sender : l'objet dans lequel l'vnement s'est produit. - Un argument de type EventArgs qui contient les informations relatives l'vnement.

Prof: Charles Jean Robelkend

54

IV. Rcuprer un vnement dans un gestionnaire d'venmentsPour rcuprer un vnement, la premire chose faire est de se placer l'coute de cet vnement. C'est l que le delegate que nous avons dclar plus haut trouve toute son utilit. La syntaxe pour ajouter un gestionnaire d'venments ("Event handler") l'coute d'un vnement est la suivante :Prof: Charles Jean Robelkend 55

IV. Rcuprer un vnement dans un gestionnaire d'venmentsLa syntaxe pour ajouter un gestionnaire d'venments ("Event handler") l'coute d'un vnement est la suivante :private GenerateText myTextGenerator = new GenerateText(); myTextGenerator.OnTextChanged+=new TutoEvent.GenerateText.TextGeneratedEventHandler( myTextGenerator_MonEvenement);

Prof: Charles Jean Robelkend

56

IV. Rcuprer un vnement dans un gestionnaire d'venmentsNote : pour qu'une mthode ne soit plus l'coute d'un vnement, il faut employer la syntaxe suivante :myTextGenerator.OnTextChanged-=new TutoEvent.GenerateText.TextGeneratedEvent Handler(myTextGenerator_MonEvenement);

Prof: Charles Jean Robelkend

57

Travaux de recherche (10%)TreeView ProgressBar ListView NumericUpDown MonthCalendar

Prof: Charles Jean Robelkend

58

3 : Architectures 3 couches

1. Introduction La pratique montre qu'isoler les diffrents traitements dans des classes spares amliorait la maintenabilit des applications. L'architecture d'une application ainsi structure est la suivante :IU Utilisateur Mtier Accs aux donnes

Donnes

SPRING

Prof: Charles Jean Robelkend

59

3 : Architectures 3 couches, tests unitaires Nunit.

La solution 3 couches inclut des traitements classiques en programmation : 1. la rcupration de donnes mmorises dans des fichiers, bases de donnes. 2. le dialogue avec l'utilisateur(affichages) 3. l'utilisation d'un algorithme mtier.On appelle cette architecture, "architecture trois tiers", traduction de l'anglais "three tier architecture". Le terme "trois tiers" dsigne normalement une architecture o chaque tier est sur une machine diffrente. Lorsque les tiers sont sur une mme machine,l'architecture devient une architecture trois couches .Prof: Charles Jean Robelkend 60

3 : Architectures 3 couches, tests unitaires Nunit.

La couche metier La couche [metier] est celle qui contient les rgles mtier de l'application. Accs aux donnes La couche d'accs aux donnes ou [dao] (DAO = Data Access Object) pour les donnes dj enregistres dans des fichiers ou bases de donnes. Interface avec l'utilisateur La couche d'interface avec l'utilisateur ou [ui] (UI = User Interface) pour les donnes saisies par l'utilisateur ou affiches l'utilisateur.

Prof: Charles Jean Robelkend

61

3 : Architectures 3 couches, tests unitaires Nunit.

de faon gnrale, la couche [dao] s'occupe de l'accs aux donnes persistantes (fichiers, bases de donnes) ou non persistantes (rseau, capteurs, ...). la couche [ui] elle, s'occupe des interactions avec l'utilisateur s'il y en a un. les trois couches sont rendues indpendantes grce l'utilisation d'interfaces(Non pas interface Utilisateur).

Prof: Charles Jean Robelkend

62

3 : Architectures 3 couches, tests unitaires Nunit.

Dans ce type d'architecture, c'est souvent l'utilisateur qui prend les initiatives. Il fait une demande en [1] et reoit une rponse en [8]. On appelle cela le cycle demande - rponse. Prenons l'exemple du calcul de l'impt d'un contribuable. Celui-ci va ncessiter plusieurs tapes : (a) la couche [ui] peut par exemple demander l'utilisateur son nombre d'enfants, son statut marital et son salaire annuel. C'est l'opration[1] (b) ceci fait, la couche [ui] va demander la couche mtier de faire le calcul de l'impt. Pour cela elle va lui transmettre les donnes qu'elle a reues de l'utilisateur. C'est l'opration [2].

Prof: Charles Jean Robelkend

63

3 : Architectures 3 couches, tests unitaires Nunit.

(c) la couche [metier] a besoin de certaines informations pour mener bien son travail : les tranches d'impt. Elle va demander ces informations la couche [dao] avec le chemin [3, 4, 5, 6]. [3] est la demande initiale et [6] la rponse cette demande. (d) ayant toutes les donnes dont elle avait besoin, la couche [metier] calcule l'impt. (e) la couche [metier] peut maintenant rpondre la demande de la couche [ui] faite en (b). C'est le chemin [7]. (f) la couche [ui] va mettre en forme ces rsultats puis les prsenter l'utilisateur. C'est le chemin [8].

Prof: Charles Jean Robelkend

64

3 : Architectures 3 couches, tests unitaires Nunit.

(g) on pourrait imaginer que l'utilisateur fait des simulations d'impt et qu'il veuille mmoriser celles-ci. Il utilisera le chemin [1-8] pour le faire. On voit dans cette description qu'une couche est amene utiliser les ressources de la couche qui est sa droite, jamais de celle qui est sa gauche. Considrons deux couches contiges :Couche A1

Couche B

2

Prof: Charles Jean Robelkend

65

3 : Architectures 3 couches, tests unitaires Nunit.

La couche [A] fait des demandes la couche [B]. Dans les cas les plus simples, une couche est implmente par une unique classe. Une application volue au cours du temps. Ainsi la couche [B] peut avoir des classes d'implmentation diffrentes [B1, B2, ...]. Si la couche [B] est la couche [dao], celle-ci peut avoir une premire implmentation [B1] qui va chercher des donnes dans un fichier. Quelques annes plus tard, on peut vouloir mettre les donnes dans une base de donnes. On va alors construire une seconde classe d'implmentation [B2]. Si dans l'application initiale, la couche [A] travaillait directement avec la classe [B1] on est obligs de rcrire partiellement le code de la couche [A]. Supposons par exemple qu'on ait crit dans la couche [A] quelque chose comme suit :Prof: Charles Jean Robelkend 66

3 : Architectures 3 couches, tests unitaires Nunit.

1. B1 b1=new B1(...); 2. .. 3. b1.getData(...); ligne 1 : une instance de la classe [B1] est cre ligne 3 : des donnes sont demandes cette instance

Prof: Charles Jean Robelkend

67

3 : Architectures 3 couches, tests unitaires Nunit.

Si on suppose, que la nouvelle classe d'implmentation [B2] utilise des mthodes de mme signature que celle de la classe [B1], il faudra changer tous les [B1] en [B2]. Ca, c'est le cas trs favorable et assez improbable si on n'a pas prt attention ces signatures de mthodes. Dans la pratique, il est frquent que les classes [B1] et [B2] n'aient pas les mmes signatures de mthodes et que donc une bonne partie de la couche [A] doive tre totalement rcrite.

Prof: Charles Jean Robelkend

68

3 : Architectures 3 couches, tests unitaires Nunit.

On peut amliorer les choses si on met une interface entre les couches [A] et [B]. Cela signifie qu'on fige dans une interface les signatures des mthodes prsentes par la couche [B] la couche [A]. Le schma prcdent devient alors le suivant :

1Couche A Interface IB

2 Couche B

4

3

Prof: Charles Jean Robelkend

69

3 : Architectures 3 couches, tests unitaires Nunit.

La couche [A] ne s'adresse dsormais plus directement la couche [B] mais son interface [IB]. Ainsi dans le code de la couche [A], la classe d'implmentation [Bi] de la couche [B] n'apparat qu'une fois, au moment de l'implmentation de l'interface [IB]. Ceci fait, c'est l'interface [IB] et non sa classe d'implmentation qui est utilise dans le code. Le code prcdent devient celui-ci : 1. IB ib=new B1(...); 2. .. 3. ib.getData(...);

Prof: Charles Jean Robelkend

70

3 : Architectures 3 couches, tests unitaires Nunit.

ligne 1 : une instance [ib] implmentant l'interface [IB] est cre ligne 3 : des donnes sont demandes l'instance [ib] Dsormais si on remplace l'implmentation [B1] de la couche [B] par une implmentation respectent la mme interface [IB], alors seule la ligne 1 de la couche [A] doit qui lui seul justifie l'usage systmatique des interfaces entre deux couches.

Prof: Charles Jean Robelkend

71

3 : Architectures 3 couches, tests unitaires Nunit.

On peut aller encore plus loin et rendre la couche [A] totalement indpendante de la couche [B]. Dans le code ci-dessus, la ligne 1 pose problme parce qu'elle rfrence en dur la classe [B1]. L'idal serait que la couche [A] puisse disposer d'une implmentation de l'interface [IB] sans avoir nommer de classe. Ce serait cohrent avec notre schma ci-dessus. On y voit que la couche [A] s'adresse l'interface [IB] et on ne voit pas pourquoi elle aurait besoin de connatre le nom de la classe qui implmente cette interface. Ce dtail n'est pas utile la couche [A].

Prof: Charles Jean Robelkend

72

3 : Architectures 3 couches, tests unitaires Nunit.1 Couche A Interface IB 2 Couche B

4SPRING

3

Prof: Charles Jean Robelkend

73

3 : Architectures 3 couches, tests unitaires Nunit.

La couche transversale [Spring] va permettre une couche d'obtenir par configuration une rfrence sur la couche situe sa droite sans avoir connatre le nom de la classe d'implmentation de la couche. Ce nom sera dans les fichiers de configuration et non dans le code C#. Le code C# de la couche [A] prend alors la forme suivante : 1. IB ib; // initialis par Spring 2. .. 3. ib.getData(...);

Prof: Charles Jean Robelkend

74

3 : Architectures 3 couches, tests unitaires Nunit.

ligne 1 : une instance [ib] implmentant l'interface [IB] de la couche [B]. Cette instance est cre par Spring sur la base d'informations trouves dans un fichier de configuration. Spring va s'occuper de crer : l'instance [b] implmentant la couche [B] l'instance [a] implmentant la couche [A]. Cette instance sera initialise. Le champ [ib] ci-dessus recevra pour valeur la rfrence [b] de l'objet implmentant la couche [B] ligne 3 : des donnes sont demandes l'instance [ib]

Prof: Charles Jean Robelkend

75

3 : Architectures 3 couches, tests unitaires Nunit.

On voit maintenant que, la classe d'implmentation [B1] de la couche B n'apparat nulle part dans le code de la couche [A]. Lorsque l'implmentation [B1] sera remplace par une nouvelle implmentation [B2], rien ne changera dans le code de la classe [A]. On changera simplement les fichiers de configuration de Spring pour instancier [B2] au lieu de [B1]. Le couple Spring et interfaces C# apporte une amlioration dcisive la maintenance d'applications en rendant les couches de celles-ci tanches entre elles. C'est cette solution que nous utiliserons pour une nouvelle version de l'application [Impots].

Prof: Charles Jean Robelkend

76

3 : Tests unitaires.

Les tests faits jusqu' maintenant pour nos diverses applications reposaient sur une vrification visuelle. On vrifiait qu'on obtenait l'cran ce qui tait attendu. C'est une mthode inutilisable lorsqu'il y a de nombreux tests faire. L'tre humain est en effet sujet la fatigue et sa capacit vrifier des tests s'mousse au fil de la journe. Les tests doivent alors tre automatiss et viser ne ncessiter aucune intervention humaine.

Prof: Charles Jean Robelkend

77

3 : Tests unitaires.

Une application volue au fil du temps. A chaque volution, on doit vrifier que l'application ne "rgresse" pas, c.a.d. qu'elle continue passer les tests de bon fonctionnement qui avaient t faits lors de son criture initiale. On appelle ces tests, des tests de "non rgression". Une application un peu importante peut ncessiter des centaines de tests. On teste en effet chaque mthode de chaque classe de l'application. On appelle cela des tests unitaires. Ceux-ci peuvent mobiliser beaucoup de dveloppeurs s'ils n'ont pas t automatiss.Prof: Charles Jean Robelkend 78

3 : Tests unitaires.

Des outils ont t dvelopps pour automatiser les tests. L'un d'eux s'appelle NUnit. Il est disponible sur le site [http://www.nunit.org] :

Prof: Charles Jean Robelkend

79

3 : Tests unitaires.

I. Invariance d'un rsultat de calcul II. Invariance d'une caractristique III. Invariance lors de la persistance IV. Invariance par inversion et autres oprations

Prof: Charles Jean Robelkend

80

3 : Tests unitaires.

I. Invariance d'un rsultat de calculCe principe consiste a obtenir des rsultats constants pour une mthode par exemple faisant des calculs quand on reproduit les mmes situations. Lune des erreurs frquentes des mthodes faisant des calculs est de retourner des rsultats diffrents pour les mmes paramtres aprs plusieurs appels.

Prof: Charles Jean Robelkend

81

3 : Tests unitaires.

I.

Exemple de mthode au rsultat variantpublic class ClasseQuiImplementeUnCalculComplexe { private int etat_initial; public ClasseQuiImplementeUnCalculComplexe (int valeur) { etat_initial = valeur; } public int Calcule(int parametre) { int resultat = etat_initial + parametre; etat_initial = parametre; // ERREUR ICI return resultat; } }

Prof: Charles Jean Robelkend

82

3 : Tests unitaires.

I.

Exemple de mthode au rsultat variantSi voud generez votre test avec les outils de visual Studio vous aurez le code suivant. [TestMethod()] public void CalculeTest() { int etat_initial = 100; ClasseQuiImplementeUnCalculComplexe target = new ClasseQuiImplementeUnCalculComplexe(etat_initial); int parametre = 10; int valeur_attendue = 110; int valeur_calculee = target.Calcule(parametre); Assert.AreEqual(valeur_attendue , valeur_calculee); }

Prof: Charles Jean Robelkend

83

3 : Tests unitaires.

Et malheureusement ce genre de test ne capture pas le problme d'initialisation que j'ai sournoisement introduit dans les lignes de code cidessus (des milliers dans la ralit). En fait il nous faut un test du type :

Prof: Charles Jean Robelkend

84

3 : Tests unitaires.

[TestMethod()] public void CalculeDoitToujoursDonnerLeMemeResultat() { int etat_initial = 100; ClasseQuiImplementeUnCalculComplexe target = new ClasseQuiImplementeUnCalculComplexe(etat_ini tial); int parametre = 50; Assert.AreEqual(target.Calcule(parametre), target.Calcule(parametre)); }

Prof: Charles Jean Robelkend

85

3 : Tests unitaires.

Dans ce deuxime test on a volontairement vit de prciser la valeur attendue, afin d'attirer votre attention sur le fait que l'on peut programmer des tests trs pertinents sans mme connatre prcisment la valeur attendue. Cela parat trs important car dans la vie relle il n'est pas toujours simple de spcifier prcisment une valeur attendue - il est alors trs agrable de pouvoir raliser des tests indirects comme celui ci-dessus.Prof: Charles Jean Robelkend 86

3 : Tests unitaires .

II. Invariance d'une caractristiqueCet exemple provient d'une autre application scientifique, dans laquelle un objet mtier complexe devait subir une transformation particulire qui produisait deux nouveaux objets remplaant le premier. L'algorithme de la transformation tait relativement complexe et il n'tait pas possible de prdire trs prcisment les nouvelles caractristiques des objets obtenus - dans le sens o l'on pouvait facilement les dterminer 10-2 prs mais pas 10-8 prs. Le test tait manuel, et consistait vrifier que des valeurs calcules correspondaient aux valeurs attendues 10-2.

Prof: Charles Jean Robelkend

87

3 : Tests unitaires .

II. Invariance d'une caractristiquePour illustrer notre propos, nous pouvons considrer que l'objet mtier est un Rectangle, que l'on s'intresse sa Surface, et que la transformation consiste le Partager en deux.

Prof: Charles Jean Robelkend

88

3 : Tests unitaires.

II. Invariance d'une caractristiquepublic class Rectangle { private readonly double largeur; private readonly double longueur ; public Rectangle (double largeur, double longueur) { this.longueur = longueur; this.largeur = largeur; } public double Surface() { return longueur*largeur; } public List Partage() { List resultat = new List(); // le calcul du milieu est intentionnellement faux int milieu = (int) longueur/2; resultat.Add(new Rectangle(largeur, milieu)); resultat.Add(new Rectangle(largeur, milieu)); return resultat; } } Prof: Charles Jean Robelkend

89

3 : Tests unitaires .

II. Invariance d'une caractristiqueDans notre cas rel il y avait une erreur subtile dans la transformation (elle est simule ci-dessus par le calcul du milieu qui est faux car ralis avec une division entire). Elle est reste indtecte jusqu' ce que quelqu'un ait l'ide dappliquer cette transformation plusieurs fois de suite et constate alors une variation inattendue sur une caractristique globale. En effet la surface totale de tous les objets se mettait diminuer, alors qu'elle aurait d rester strictement constante. Nous n'avions pas pens exploiter le fait que cette surface tait invariante dans cette transformation, ce qui aurait t bien plus simple vrifier manuellement que de vrifier des valeurs particulires une certaine prcision.Prof: Charles Jean Robelkend 90

3 : Tests unitaires.

II. Invariance d'une caractristiqueL'automatisation des tests, si l'on ne fait pas explicitement attention exploiter une telle caractristique invariante, peut tout fait rencontrer ce genre de problme. En effet, on risque de se limiter des mthodes de test comme celle ci-dessous, qui est l'quivalent de notre test manuel initial dans lequel on se contentait d'une faible prcision car on ne connaissait pas exactement la valeur attendue :

Prof: Charles Jean Robelkend

91

3 : Tests unitaires.public void PartageTest() { const double FAIBLE_PRECISION = 1E-2; double largeur = 10; double longueur = 20.05; double surface_attendue = 100; Rectangle target = new Rectangle(largeur, longueur); List rectangles = target.Partage(); Assert.AreEqual(surface_attendue, rectangles[0].Surface(), FAIBLE_PRECISION); Assert.AreEqual(surface_attendue, rectangles[1].Surface(), FAIBLE_PRECISION); }

Prof: Charles Jean Robelkend

92

3 : Tests unitaires.

II. Invariance d'une caractristiqueCe test russit malgr l'erreur introduite dans la mthode Partage ! Par contre si l'on prend en compte l'invariance de la surface totale, on peut exiger une grande prcision dans le test, car mme sans connatre la valeur attendue on sait qu'elle doit tre exactement la mme que la valeur initiale :

Prof: Charles Jean Robelkend

93

3 : Tests unitaires.public void PartageDoitConserverLaSurfaceTotale() { const double HAUTE_PRECISION = 1E-8; double largeur = 10; double longueur = 20.05; Rectangle target = new Rectangle(largeur, longueur); List rectangles = target.Partage(); Assert.AreEqual(target.Surface(), rectangles[0].Surface() + rectangles[1].Surface(), HAUTE_PRECISION); }

Et ce moment-l le test choue et capture bien l'erreur dans Partage.

Prof: Charles Jean Robelkend

94

3 : Tests unitaires.

III. Invariance lors de la persistanceDans nos applications nous sommes trs souvent amens faire persister des objets dans un support externe au programme, typiquement des fichiers. Si on prend le point de vue de la vrification de l'invariance, la squence d'oprations SauveDansFichier, LitDepuisFichier, SauveDansFichier doit produire toujours le mme fichier. Si ce n'est pas le cas il y a une erreur dans l'une de ces oprations. Par une erreur typique serait l'oubli de lire une proprit dans LitDepuisFichier, ou encore une erreur d'affectation (par exemple lire correctement longueur et largeur, mais affecter les deux valeurs au mme champ. Voici un test qui pourrait capturer de tels problmes :Prof: Charles Jean Robelkend 95

3 : Tests unitaires.

[TestMethod()] public void SauvegardeDoitConserverInformation( ) { Rectangle original = new Rectangle(10, 100); original.SauveDansFichier("original.txt "); Rectangle copie = new Rectangle(0,0); copie.LitDepuisFichier("original.txt"); copie.SauveDansFichier("copie.txt"); string original_texte;Prof: Charles Jean Robelkend 96

3 : Tests unitaires.

string copie_texte; using (StreamReader sr = File.OpenText( "original.txt")) { original_texte = sr.ReadToEnd(); } using (StreamReader sr = File.OpenText("copie.txt")) { copie_texte = sr.ReadToEnd(); } Assert.AreEqual(original_texte,copie_t exte); }Prof: Charles Jean Robelkend 97

3 : Tests unitaires.

On retrouve nouveau ce qui semble une proprit intressante de ces tests sur l'invariance : il n'est pas ncessaire de contrler le contenu prcis du fichier gnr pour crire un test pertinent. Bien sr ce test ne remplace pas les autres tests qui seraient ncessaires dans ce contexte, car il ne vrifie pas que l'on sauvegarde bien ce que l'on est suppos sauvegarder. Sa vocation est plutt de complter d'autres tests portant sur le contenu.Prof: Charles Jean Robelkend 98

3 : Tests unitaires.

IV. Invariance par inversion et autres oprationsLes ides dveloppes ci-dessus s'appliquent en fait, dans un contexte de calcul scientifique, toute opration disposant d'une opration inverse (au sens ou 1/X est l'inverse de X). Voici un exemple basique : supposons que vous ayez dvelopp votre propre mthode pour calculer la racine carre d'un nombre. En recherchant un test bas sur le principe de vrification de l'invariance, vous pourriez arriver :Prof: Charles Jean Robelkend 99

3 : Tests unitaires.

[TestMethod()] public void InverseDoitConserverInformation() { double x = MaRacineCarree(2) ; Assert.AreEqual(x*x, 2, 1E-8) } Si cet exemple peut paratre trop trivial, considrez alors celui-ci (driv galement d'une application scientifique raliste) :Prof: Charles Jean Robelkend 100

3 : Tests unitaires.

[TestMethod()] public void FusionDoitConserverLaSurfaceTotale() { const double HAUTE_PRECISION = 1E-8; double largeur = 10; double longueur = 20.05; Rectangle target = new Rectangle(largeur, longueur); List rectangles = target.Partage(); Rectangle rectangle_fusion = rectangles[0].FusionneAvec(rectangles[1]); Assert.AreEqual(target.Surface(), rectangle_fusion.Surface(), HAUTE_PRECISION); }

Prof: Charles Jean Robelkend

101

4 : Accs aux base de donnes

4.1 CONNECTEUR ADO.NET 4.2 LES DEUX MODES D'EXPLOITATION D'UNE SOURCE DE DONNES 4.3 LES CONCEPTS DE BASE DE L'EXPLOITATION D'UNE BASE DE DONNES 4.3.1 LES QUATRE COMMANDES DE BASE DU LANGAGE 4.3.2 LES INTERFACES DE BASE D'ADO.NET POUR LE MODE CONNECT 4.3.3 LA GESTION DES ERREURS 4.3.4 EXCUTION D'UNE REQUTE SELECT. 4.3.5 EXCUTION D'UN ORDRE DE MISE JOUR : INSERT, UPDATE, DELETE

Prof: Charles Jean Robelkend

102

4 : Accs aux base de donnes

Dans les exemples tudis, la couche [dao] a pour l'instant exploit deux types de sources de donnes : des donnes places en dur dans le code des donnes provenant de fichiers texte Nous tudions dans ce chapitre le cas o les donnes proviennent d'une base de donnes. L'architecture 3 couches volue alors vers une architecture multi-couches. Il en existe diverses. Nous allons tudier les concepts de base avec la suivante :

Prof: Charles Jean Robelkend

103

4 : Accs aux base de donnes

DAO

Connecteur ADO.NET

SGBD

BD

Prof: Charles Jean Robelkend

104

4 : Accs aux base de donnes

Dans le schma ci-dessus, la couche [dao] [1] dialogue avec le SGBD [3] au travers d'une bibliothque de classes propre au SGBD utilis et livre avec lui. Cette couche implmente des fonctionnalits standard runies sous le vocable ADO (Active X Data Objects). On appelle une telle couche, un provider (fournisseur d'accs une base de donnes ici) ou encore connecteur. La plupart des SGBD disposent dsormais d'un connecteur ADO.NET, ce qui n'tait pas le cas aux dbuts de la plate-forme .NET.Prof: Charles Jean Robelkend 105

4 : Accs aux base de donnes

Les connecteurs .NET n'offrent pas une interface standard la couche [dao], aussi celle-ci a-t-elle dans son code le nom des classes du connecteur. Si on change de SGBD, on change de connecteur et de classes et il faut alors changer la couche [dao]. C'est la fois une architecture performante parce le connecteur .NET ayant t crit pour un SGBD particulier sait utiliser au mieux celui-ci et rigide car changer de SGBD implique de changer la couche [dao].

Prof: Charles Jean Robelkend

106

4 : Accs aux base de donnes

Ce deuxime argument est relativiser : les entreprises ne changent pas de SGBD trs souvent. Par ailleurs, nous verrons ultrieurement que depuis la version 2.0 de .NET, il existe un connecteur gnrique qui amne de la souplesse sans sacrifier la performance.

Prof: Charles Jean Robelkend

107

Les deux modes d'exploitation d'une source de donnes

La plate-forme .NET permet l'exploitation d'une source de donnes de deux manires diffrentes: 1. mode connect 2. mode dconnect En mode connect, l'application 1. ouvre une connexion avec la source de donnes 2. travaille avec la source de donnes en lecture/criture 3. ferme la connexion 3. ferme la connexion

Prof: Charles Jean Robelkend

108

Les deux modes d'exploitation d'une source de donnes

En mode dconnect, l'application 1. ouvre une connexion avec la source de donnes 2. obtient une copie mmoire de tout ou partie des donnes de la source 3. ferme la connexion 4. travaille avec la copie mmoire des donnes en lecture/criture 5. lorsque le travail est fini, ouvre une connexion, envoie les donnes modifies la source de donnes pour qu'elle les prenne en compte, ferme la connexionProf: Charles Jean Robelkend 109

Les concepts de base de l'exploitation d'une base de donnes

Prof: Charles Jean Robelkend

110

Les quatre commandes de base du langage SQL

SQL (Structured Language Query) est un langage, partiellement normalis, d'interrogation et de mise jour des bases de donnes. Tous les SGBD respectent la partie normalise de SQL mais ajoutent au langage des extensions propritaires qui exploitent certaines particularits du SGBD.Les quatre commandes de base du langage SQL que nous prsentons sont normalises et acceptes par tous les SGBD ce sont : Select,Insert,Update et Delete.Prof: Charles Jean Robelkend 111

Les interfaces de base d'ADO.NET pour le mode connect

Trois interfaces ADO.NET sont principalement concernes par ces oprations : IDbConnection qui encapsule les proprits et mthodes de la connexion. IDbCommand qui encapsule les proprits et mthodes de la commande SQL excute. IDataReader qui encapsule les proprits et mthodes du rsultat d'un ordre SQL Select.

Prof: Charles Jean Robelkend

112

Les interfaces de base d'ADO.NET pour le mode connect

L'interface IDbConnection Sert grer la connexion avec la base de donnes. Les mthodes M et proprits P de cette interface que nous utiliserons seront les suivantes :

Prof: Charles Jean Robelkend

113

Les interfaces de base d'ADO.NET pour le mode connect

ConnectionString , P chane de connexion la base. Elle prcise tous les paramtres ncessaires l'tablissement de la connexion avec une base prcise. Open, M ouvre la connexion avec la base dfinie par ConnectionString Close, M ferme la connexion BeginTransaction, M dmarre une transaction. State, P tat de la connexion : ConnectionState.Closed, ConnectionState.Open, ConnectionState.Connecting,ConnectionState.Ex ecuting, ConnectionState.Fetching, ConnectionState.BrokenJean Robelkend Prof: Charles 114

Les interfaces de base d'ADO.NET pour le mode connect

L'interface IDbCommand Sert excuter un ordre SQL ou une procdure stocke. Les mthodes M et proprits P de cette interface que nous utiliserons seront les suivantes :

Prof: Charles Jean Robelkend

115

Les interfaces de base d'ADO.NET pour le mode connectCommandType P indique ce qu'il faut excuter - prend ses valeurs dans une numration : CommandType.Text : excute l'ordre SQL dfini dans la proprit CommandText. C'est la valeur par dfaut. - CommandType.StoredProcedure : excute une procdure stocke dans la base CommandText P - le texte de l'ordre SQL excuter si CommandType= CommandType.Text - le nom de la procdure stocke excuter si CommandType= CommandType.StoredProcedure Connection P la connexion IDbConnection utiliser pour excuter l'ordre SQL Transaction P la transaction IDbTransaction dans laquelle excuter l'ordre SQL Parameters P la liste des paramtres d'un ordre SQL paramtr. L'ordre update articles set prix=prix*1.1 where id=@id a le paramtre @id. ExecuteReader M pour excuter un ordre SQL Select. On obtient un objet IDataReader reprsentant le rsultat du Select.Prof: Charles Jean Robelkend 116

Les interfaces de base d'ADO.NET pour le mode connectNom Type Rle ExecuteNonQuery M pour excuter un ordre SQL Update, Insert, Delete. On obtient le nombre de lignes affectes par l'opration (mises jour, insres, dtruites). ExecuteScalar M pour excuter un ordre SQL Select ne rendant qu'un unique rsultat comme dans : select count(*) from articles. CreateParameter M pour crer les paramtres IDbParameter d'un ordre SQL paramtr. Prepare M permet d'optimiser l'excution d'une requte paramtre lorsqu'elle est excute de multiples fois avec des paramtres diffrents.

Prof: Charles Jean Robelkend

117

Les interfaces de base d'ADO.NET pour le mode connectSi Command est une classe implmentant l'interface IDbCommand, l'excution d'un ordre SQL sans transaction aura la forme suivante:1. // ouverture connexion 2. IDbConnection connexion=... 3. connexion.Open(); 4. // prparation commande 5. IDbCommand commande=new Command(); 6. commande.Connection=connexion; 7. // excution ordre select 8. commande.CommandText="select ..."; 9. IDbDataReader reader=commande.ExecuteReader(); 10. ... 11. // excution ordre update, insert, delete 12. commande.CommandText="insert ..."; 13. int nbLignesInsres=commande.ExecuteNonQuery(); 14. ... 15. // fermeture connexion 16. connexion.Close();Prof: Charles Jean Robelkend 118

Les interfaces de base d'ADO.NET pour le mode connect

L'interface IDataReader Sert encapsuler les rsultats d'un ordre SQL Select. Un objet IDataReader reprsente une table avec des lignes et des colonnes, qu'on exploite squentiellement : d'abord la 1re ligne, puis la seconde, .... Les mthodes M et proprits P de cette interface que nous utiliserons seront les suivantes :

Prof: Charles Jean Robelkend

119

Les interfaces de base d'ADO.NET pour le mode connectFieldCount P le nombre de colonnes de la table IDataReader GetName M GetName(i) rend le nom de la colonne n i de la table IDataReader. Item P Item[i] reprsente la colonne n i de la ligne courante de la table IDataReader. Read M passe la ligne suivante de la table IDataReader. Rend le boolen True si la lecture a pu se faire, False sinon. Close M ferme la table IDataReader. GetBoolean M GetBoolean(i) : rend la valeur boolenne de la colonne n i de la ligne courante de la table IDataReader. Les autres mthodes analogues sont les suivantes : GetDateTime, GetDecimal, GetDouble, GetFloat, etInt16, GetInt32, GetInt64, GetString. Getvalue M Getvalue(i) : rend la valeur de la colonne n i de la ligne courante de la table IDataReader en tant que type object. IsDBNull M IsDBNull(i) rend True si la colonne n i de la ligne courante de la table IDataReader n'a pas de valeur ce qui est symbolis par la valeur SQL NULL.

Prof: Charles Jean Robelkend

120

Les interfaces de base d'ADO.NET pour le mode connectL'exploitation d'un objet IDataReader ressemble souvent ce qui suit : 1. // ouverture connexion 2. IDbConnection connexion=... 3. connexion.Open(); 4. // prparation commande 5. IDbCommand commande=new Command(); 6. commande.Connection=connexion; 7. // excution ordre select 8. commande.CommandText="select ..."; 9. IDataReader reader=commande.ExecuteReader(); 10. // exploitation rsultats 11. while(reader.Read()){ 12. // exploiter ligne courante 13. ... 14. } 15. // fermeture reader 16. reader.Close(); 17. // fermeture connexion 18. connexion.Close();Prof: Charles Jean Robelkend 121

5 : Les Threads

5.1. Le multithreading 5.2. La classe System.Threading.Thread 5.2.1. Crer et lancer un thread 5.2.2. Passer des paramtres a un thread 5.2.3. Protger des ressources critiques 5.2.4. Stopper des threads

Prof: Charles Jean Robelkend

122

5 : Les Threads

5.1. Le multithreadingDe tout temps, l'homme a cherch amliorer sa productivit en paralllisant ses tches. Par exemple, les principes du montage la chane ou des architectures pipelines dcoulent directement de cette envie d'optimisation. En programmation aussi, il est possible de raliser ce genre de mcanisme. Pour illustrer ce besoin, prenons un exemple simple : un programme effectue divers calculs compliqus pendant un temps relativement long. L'utilisateur souhaite voir les rsultats intermdiaires apparatre sur son interface graphique en temps rel. On peut clairement sparer dans ce cas la partie calcul et l'autre partie concernant l'affichage. Plutt que de parler de parties, parlons de tches.

Prof: Charles Jean Robelkend

123

5 : Les ThreadsSi nous excutons le programme de manire squentielle, soit sans paralllisme, il y a de fortes chances pour que l'utilisateur doive attendre la fin des calculs pour qu'un affichage des rsultats apparaisse enfin. En sparant les tches calculs et affichage, chacune aura, tour de rle un petit moment allou par le processeur pour travailler. Cette mthode de programmation est aujourd'hui largement utilise et contribue beaucoup amliorer la ractivit des applications. Il faut noter que sur un systme monoprocesseur, la notion de multithreading est toute relative. En effet, le processeur ne peut rellement travailler que dans une tche la fois. Cela dit, le changement de contexte entre deux tches se faisant une vitesse si rapide, qu'il nous semble que le travail se fait simultanment et que les deux tches travaillent en mme temps. Avec un systme biprocesseur par contre, si nous avons deux tches, elles seront dispatches sur un des processeurs disponibles et elles travailleront rellement en parallle.Prof: Charles Jean Robelkend 124

5 : Les Threads

5.2. La classe System.Threading.ThreadEn programmation pure, on ne parle plus de tches, mais de threads ou de processus.

En C# et dans tous les autres langages du framework .NET, la classe Thread se trouve dans l'espace de noms System.Threading. Pour simplifier, un objet de la classe Thread symbolise une tche. L'utilisation des threads avec .NET a t fortement simplifie compare aux mthodes natives Win32. Nous allons dans ce cours voir comment crer, utiliser et dtruire des threads manags, ainsi que quelques mcanismes de protection de ressources critiques.

Prof: Charles Jean Robelkend

125

5 : Les Threads

5.2. La classe System.Threading.Thread Quelques proprits utiles : Thread CurrentThread : proprit statique qui donne une rfrence sur le thread dans lequel se trouve le code ayant demand cette proprit string Name : le nom du thread bool IsAlive : indique si le thread est en cours d'excution ou non.

Prof: Charles Jean Robelkend

126

5 : Les Threads

5.2. La classe System.Threading.Thread Les mthodes les plus utilises sont les suivantes : Start(), Start(object obj) : lance l'excution asynchrone du thread, ventuellement en lui passant de l'information dans un type object. Abort(), Abort(object obj) : pour terminer de force un thread.

Prof: Charles Jean Robelkend

127

5 : Les Threads

5.2. La classe System.Threading.Thread Les mthodes les plus utilises sont les suivantes : Join() : le thread T1 qui excute T2.Join est bloqu jusqu' ce que soit termin le thread T2. Il existe des variantes pour terminer l'attente au bout d'un temps dtermin. Sleep(int n) : mthode statique - le thread excutant la mthode est suspendu pendant n millisecondes. Il perd alors le processeur qui est donn un autre thread.

Prof: Charles Jean Robelkend

128

5 : Les Threads

5.2.1. Crer et lancer un threadIl est possible d'avoir des applications o des morceaux de code s'excutent de faon "simultane" dans diffrents threads d'excution. La portion de temps accorde un thread dpend de divers facteurs dont sa priorit qui a une valeur par dfaut mais qui peut tre fixe galement par programmation. Lorsqu'un thread dispose du processeur, il l'utilise normalement pendant tout le temps qui lui a t accord. Cependant, il peut le librer avant terme : en se mettant en attente d'un vnement (Wait, Join) en se mettant en sommeil pendant un temps dtermin (Sleep)

Prof: Charles Jean Robelkend

129

5 : Les Threads

5.2.1. Crer et lancer un thread1. Un thread T est tout d'abord cr par l'un des constructeurs prsents plus haut, par exemple :

Thread thread=new Thread(Start);o Start est une mthode ayant l'une des deux signatures suivantes : void Start(); void Start(object obj);

La cration d'un thread ne lance pas celui-ci.

Prof: Charles Jean Robelkend

130

5 : Les Threads

5.2.1. Crer et lancer un thread2. L'excution du thread T est lanc par T.Start() : la mthode Start passe au constructeur de T va alors tre excute par le thread T. Le programme qui excute l'instruction T.Start() n'attend pas la fin de la tche T : il passe aussitt l'instruction qui suit. On a alors deux tches qui s'excutent en parallle. Elles doivent souvent pouvoir communiquer entre elles pour savoir o en est le travail commun raliser. C'est le problme de synchronisation des threads.

Prof: Charles Jean Robelkend

131

5 : Les Threads

5.2.1. Crer et lancer un thread 3. Une fois lanc, le thread T s'excute de faon autonome. Il s'arrtera lorsque la mthode Start qu'il excute aura fini son travail. 4. On peut forcer le thread T se terminer : a. T.Abort() demande au thread T de se terminer. 5. On peut aussi attendre la fin de son excution par T.Join(). On a l une instruction bloquante : le programme qui l'excute est bloqu jusqu' ce que la tche T ait termin son travail. C'est un moyen de synchronisation.Prof: Charles Jean Robelkend 132

5 : Les Threads

5.2.1. Crer et lancer un thread Le lancement de l'excution d'un thread n'est pas bloquante.

Prof: Charles Jean Robelkend

133

5 : Les Threads

5.2.1. Crer et lancer un thread Le lancement de l'excution d'un thread n'est pas bloquante.

Prof: Charles Jean Robelkend

134

5 : Les Threads

5.2.2. Passer des paramtres a un thread La mthode de cration de threads avec le dlgu ThreadStart ne permet pas de passer directement des paramtres. Il existe un moyen trs simple pour contourner ce souci : il suffit de crer une classe spcifique qui contient la mthode du thread (ThreadLoop dans l'exemple ci-dessus). On utilisera alors les membres de cette classe comme paramtres.

Prof: Charles Jean Robelkend

135

5 : Les Threads

5.2.2. Passer des paramtres a un thread // On cre notre 'manipulateur' de thread en y //passant un // paramtre classique MyThreadHandle threadHandle = new MyThreadHandle(10); // On cre notre thread en y donnant comme mthode boucle, une // mthode membre de notre manipulateur Thread t = new Thread(new ThreadStart(threadHandle.ThreadLoop)); // La mthode ThreadLoop de l'objet //threadHandle est appele, et myParam est //donc accessible! Prof: Charles Jean Robelkend t.Start();

136

5 : Les Threads

5.2.3. Protger des ressources critiquesUne ressource est dite critique si sa modification ne doit pas tre interrompue. Par exemple, considrons une zone de code critique de 5 lignes. Si la tche se trouve actuellement la 3me ligne de cette zone et qu'elle perd le processeur, certaines donnes seront errones, ou perdues, voire pire encore. Il faut donc prciser au CLR qu'une certaine zone de code ne doit pas tre interrompue par d'autres tches. Pour raliser ceci, C# propose un mcanisme extrmement simple avec le mot-cl lock. La directive lock avant une portion de code ou une dclaration permettra d'viter le problme de l'exclusion mutuelle (mutex). Imaginons que plusieurs tches accdent une ressource critique pour y dbiter un montant.Prof: Charles Jean Robelkend 137

5 : Les Threadsusing System; using System.Threading; class ThreadedApp { public static void Main() { // Dclaration du thread Thread myThread; // Instanciation du thread, on spcifie dans le // dlgu ThreadStart le nom de la mthode qui // sera excute lorsque l'on appele la mthode // Start() de notre thread myThread = new Thread(new ThreadStart(ThreadLoop)); // Lancement du thread myThread.Start(); }

Prof: Charles Jean Robelkend

138

5 : Les Threads// Cette mthode est appel lors du lancement du thread // C'est ici qu'il faudra faire notre travail. public static void ThreadLoop() { // Tant que le thread n'est pas tu, on travaille while (Thread.CurrentThread.IsAlive) { // Attente de 500 ms Thread.Sleep(500); // Affichage dans la console Console.WriteLine("Je travaille..."); } } }

Prof: Charles Jean Robelkend

139

5 : Les Threads

5.2.3. Protger des ressources critiquespublic class MyThreadHandle { // Cet entier sera utilis comme paramtre int myParam; / // Constructeur public MyThreadHandle (int myParam) { this.myParam = myParam; } // Mthode de modification du paramtre public void SetParam(int param) { this.myParam = param; } // Mthode boucle du thread public void ThreadLoop() { // On peut utiliser ici notre paramtre myParam switch (myParam) { // ... } } }

Prof: Charles Jean Robelkend

140

5 : Les Threads

5.2.3. Protger des ressources critiquesprivate void DebiterCompte(int Montant) { // Le code dans le bloc suivant sera protg lock (this) { Console.WriteLine("Solde avant transaction : " + Solde); Console.WriteLine("Montant dbiter : " + Montant); // Code critique Solde = Solde - Montant; Console.WriteLine("Solde aprs transaction : " + Solde); } }

Prof: Charles Jean Robelkend

141

5 : Les Threads

5.2.4. Stopper des threads A tout moment, on peut tre amen vouloir explicitement dtruire des threads, par exemple lors de la fermeture du programme, histoire de faire les choses proprement. La mthode la plus sche pour stopper un thread se nomme Abort. Celle-ci tue le thread et lve une exception du type ThreadAbortException. Une autre mthode utile, mais dont l'effet est diffrent, est Suspend. En appelant cette mthode, le thread sera mis en attente jusqu'au moment o la mthode Resume sera appele sur le thread en question.Prof: Charles Jean Robelkend 142

6 : Programmation Internet

6.1. Les sockets 6.2. La classe Socket 6.2.1. Crer une socket 6.2.2. Connexion-Ecoute 6.2.3. Transmission de donnes 6.2.3.1 Envoi de donnes 6.2.3.2 Rception de donnes 6.2.4. Fermeture de la socket 6.3. Les classe du Framework .Net 6.3.1 La classe TcpClient 6.3.2 La classe TcpListener

Prof: Charles Jean Robelkend

143

6 : Programmation rseau

6.1. Les sockets La programmation rseau repose sur les sockets. Les sockets sont une norme de communication sur rseau, mis au point Berkeley, qui permettent une application, de dialoguer avec un protocole. Cela peut-tre fait sur une mme machine, ou bien sur une machine distante, au travers d'un rseau. Il existe 2 modes de communications pour les sockets : - le mode connect, qui utilise le protocole TCP - le mode dconnect, qui repose sur le protocole UDPProf: Charles Jean Robelkend 144

6 : Programmation rseau

6.1. Les sockets Le Framework .Net dispose de nombreuses classes destines facilites la programmation rseau. L'ensemble de ces classes est intgr dans les espaces de noms System.Net et System.Net.Sockets. Ces classes constituent le minimum utiliser pour le dveloppement d'une application rseau.

Prof: Charles Jean Robelkend

145

6 : Programmation rseau/Crer une socket

6.2. La classe Socket La classe Socket du Framework .Net est la base de la programmation rseau.

Prof: Charles Jean Robelkend

146

6 : Programmation rseau/Crer une socket/La classe Socket

6.2.1. Crer une socket Pour crer une socket, vous devez l'instancier, au moyen de son constructeur (les paramtres du constructeur sont des numrations, dpendantes les unes des autres) : Socket (AddressFamily famille, SocketType type, ProtocolType protocole) AdressFamily est le type de l'adresse utilise : AppleTalk, InterNetwork (IP), InterNetworkV6 (IPv6), etc SocketType est le type de socket utilise : Raw, Stream, etc ProtocolType est le protocole utilis : Ip, Tcp, Udp, Ipx, etcProf: Charles Jean Robelkend 147

6 : Programmation rseau/Crer une socket/La classe Socket

6.2.1. Crer une socket Exemple de cration d'une socket : Socket _socket = new Socket (AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

Prof: Charles Jean Robelkend

148

6 : Programmation rseau/Crer une socket/La classe Socket

6.2.2. Connexion-Ecoute La connexion une socket se fait via la mthode Connect de l'objet Socket. Cette mthode prend en paramtre un IpEndPoint, qui permet de spcifier sur quelle IP et sur quel port notre socket doit se connecter. Exemple : _socket.Connect (new IpEndPoint (Dns.Resolve ("www.developpez.com").AddressList[0], 80));

Prof: Charles Jean Robelkend

149

6 : Programmation rseau/Crer une socket/La classe Socket

6.2.2. Connexion-Ecoute Il est galement possible de crer une socket d'coute, au moyen de la mthode Listen. Celleci prend en paramtre le numro du port sur lequel la socket doit couter.

Prof: Charles Jean Robelkend

150

6 : Programmation rseau/Crer une socket/Transmission

6.2.3.1 Envoi de donnes Pour envoyer des donnes, vous devez utiliser la mthode Send, qui comprend plusieurs surcharges : Send (Byte [] Message [, indice de dpart d'envoi][, Longueur envoyer][, SocketFlags]) Message est le message envoyer, sous forme de tableau de byte. Indice de dpart d'envoi est l'indice, dans le tableau, partir duquel lire. Longueur envoyer est le nombre d'octet envoyer. SocketFlags est une numration permettant de contrler l'envoi des donnes.Prof: Charles Jean Robelkend 151

6 : Programmation rseau/Crer une socket/Transmission

6.2.3.1 Envoi de donnes Exemple : Byte [] Message = Encoding.ASCII.GetBytes ("Test envoi de donnes"); Int OctetsEnvoyes = _socket.Send (Message, 0, Message.Length, SocketFlags.None);

Prof: Charles Jean Robelkend

152

6 : Programmation rseau/Crer une socket/Transmission

6.2.3.2 Reception de donnes La rception de donnes, quand elle, se fait au moyen simple de la mthode Receive. Tout comme la mthode Send, elle dispose de plusieurs surcharges : Receive (Byte [] MessageRecu [, indice de dpart de rception][, Longueur envoyer][, SocketFlags]) Les arguments de la mthode Receive sont identiques ceux de la mthode Send. Vous pouvez tout moment contrler l'tat de la socket, au moyen de la proprit Connected.Prof: Charles Jean Robelkend 153

6 : Programmation rseau

6.2.4. Fermeture de la socket Pour fermer une socket, vous devez, au pralable, terminer les oprations d'envois et de rception sur la socket. Ensuite, appeler la mthode ShutDown, prenant en paramtre un SocketShutDown.

Prof: Charles Jean Robelkend

154

6 : Programmation rseau

6.3. Les classe du Framework .Net On retiendra que la classe Socket est suffisante en elle-mme pour grer toute communication tcp-ip mais on cherchera avant tout utiliser les classes de plus haut niveau afin de faciliter l'criture de l'application tcp-ip.

Prof: Charles Jean Robelkend

155

6 : Programmation rseau

6.3.2 La classe TcpListener La classe TcpClient est la classe qui convient dans la plupart des cas pour crer le client d'un service TCP. Elle a parmi ses constructeurs C, mthodes M et proprits P, les suivants :

Prof: Charles Jean Robelkend

156

6 : Programmation rseau

6.3.2 La classe TcpClientTcpClient(string hostname , int port) (C) cre une liaison tcp avec le service oprant sur le port indiqu (port) de la machine indique (hostname). Par exemple new TcpClient("istia.univ-angers.fr",80) pour se connecter au port 80 de la machine istia.univ-angers.fr Socket Client (P) le socket utilis par le client pour communiquer avec le serveur. NetworkStream GetStream() (M) obtient un flux de lecture et d'criture vers le serveur. C'est ce flux qui permet les changes client-serveur. void Close() (M) ferme la connexion. Le socket et le flux NetworkStream sont galement ferms bool Connected() (P) vrai si la connexion a t tablieProf: Charles Jean Robelkend 157

6 : Programmation rseau

6.3.2 La classe TcpClientLa classe NetworkStream reprsente le flux rseau entre le client et le serveur. Elle est drive de la classe Stream. Beaucoup d'applications client-serveur changent des lignes de texte termines par les caractres de fin de ligne "\r\n". Aussi est-il intressant d'utiliser des objets StreamReader et StreamWriter pour lire et crire ces lignes dans le flux rseau. Ainsi si une machine M1 a tabli une liaison avec une machine M2 l'aide d'un objet TcpClient client1 et qu'elles changent des lignes de texte, elle pourra crer ses flux de lecture et criture de la faon suivante :

StreamReader in1=new StreamReader(client1.GetStream()); StreamWriter out1=new StreamWriter(client1.GetStream()); out1.AutoFlush=true;Prof: Charles Jean Robelkend 158

6 : Programmation rseau

6.3.2 La classe TcpClientsignifie que le flux d'criture de client1 ne transitera pas par un buffer intermdiaire mais ira directement sur le rseau. Ce point est important. En gnral lorsque client1 envoie une ligne de texte son partenaire il en attend une rponse. Celle-ci ne viendra jamais si la ligne a t en ralit bufferise sur la machine M1 et jamais envoye la machine M2. Pour envoyer une ligne de texte la machine M2, on crira : client1.WriteLine("un texte"); Pour lire la rponse de M2, on crira : string rponse=client1.ReadLine();Prof: Charles Jean Robelkend 159

6 : Programmation rseau

6.3.2 La classe TcpListener La classe TcpListener est la classe qui convient dans la plupart des cas pour crer un service TCP. Elle a parmi ses constructeurs C, mthodes M et proprits P, les suivants :

Prof: Charles Jean Robelkend

160

6 : Programmation rseau

6.3.2 La classe TcpListenerTcpListener(int port) C cre un service TCP qui va attendre (listen) les demandes des clients sur un port pass en paramtre (port) appel port d'coute. Si la machine est connecte plusieurs rseaux IP, le service coute sur chacun des rseaux. TcpListener(IPAddress ip,int port) C idem mais l'coute n'a lieu que sur l'adresse ip prcise. void Start() M lance l'coute des demandes clients TcpClient AcceptTcpClient() M accepte la demande d'un client. Ouvre alors une nouvelle connexion avec celui-ci, appele connexion de service. Le port utilis ct serveur est alatoire et choisi par le systme. On l'appelle le port de service. AcceptTcpClient rend comme rsultat l'objet TcpClient associ ct serveur la connexion de service. void Stop() M arrte d'couter les demandes clients Socket Server P le socket d'coute du serveurProf: Charles Jean Robelkend 161