Débuter la programmation Visual Basic avec les Bases de Données
12
Bases de données
est le successeur d’ADO (ActiveX Data Objects). Ses fonctionnalités permettent d’accéder simplement à des bases de données locales ou distantes. À travers un ensemble de procédures et de fonctions, il est possible de visualiser, de modifier et de supprimer les données contenues dans une base de données, que celle-ci se trouve sur l’ordinateur local ou sur un ordinateur distant.
Pour illustrer le fonctionnement d’, nous allons prendre deux exemples. Le premier permettra d’accéder à une base de données locale Microsoft Access. Le second sera une copie conforme du premier, à ceci près que les données se trouveront sur un serveur distant.
Accès à une base de données locale
Lancez la commande Nouveau/Projet dans le menu Fichier. Choisissez .NET Framework 4 dans la liste déroulante Framework. Sélectionnez Visual Basic/Windows dans le volet gauche et Application Windows Forms dans le volet central. Nommez le projet db et validez en cliquant sur OK. Ajoutez un contrôle DataGridView et quatre boutons de commande à la feuille du projet et modifiez les propriétés de ces objets comme indiqué dans le tableau suivant :
| Contrôle | Propriété | Valeur |
| Form1 | Text | Accès à une base locale |
| Button1 | Text | Bibliothèque |
| Button1 | Name | Bibliothèque |
| Button2 | Text | Tous |
| Button2 | Name | Tous |
| Button3 | Text | Mise à jour |
| Button3 | Name | MiseAJour |
| Button4 | Text | Quitter |
| Button4 | Name | Quitter |
Pour terminer la mise en forme de l’application, cliquez sur le contrôle DataGridView et affectez la valeur Top à sa propriété Dock. Pour cela, développez cette propriété en déroulant la liste Dock et cliquez sur le rectangle supérieur (voir Figure 12.1).
Figure 12.1
Affectation de la valeur Top à la propriété Dock du contrôle DataGridView1.
La feuille de l’application devrait maintenant avoir l’allure de la Figure 12.2.
Figure 12.2
L’application db mise en forme, en mode Édition.
Cette application utilise les bibliothèques et .OleDB. Ajoutez les deux instructions ci-après en tête de listing :
Imports
Imports .OleDb
Définissez les objets utilisés par l’application à la suite du code généré par Windows Form Designer :
Dim Connexion As String
Dim ConnexionOLE As OleDBConnection = New oledbConnection()
Dim da As OleDbDataAdapter
Dim ds As DataSet
Dim dv As DataView
Dim cb As OleDbCommandBuilder
L’exemple choisi repose sur une base de données Access librement téléchargeable sur la page .
Cette base contient plusieurs tables de données. Nous allons nous intéresser à l’une d’entre elles, qui a pour nom "Catégories". Pour afficher l’ensemble des enregistrements qui la composent, nous allons définir la procédure AfficheTous() :
Public Sub AfficheTous()
Connexion = ".OLEDB.4.0;Data Source=
„ C:\\"
ConnexionOLE.ConnectionString = Connexion
()
da = New OleDbDataAdapter("Select * from T_TravailObjet", ConnexionOLE) ds = New DataSet() (ds, "mytable")
dv = ds.Tables("mytable").DefaultView
ConnexionOLE.Close()
DataGridView1.DataSource = dv dv.AllowEdit = True End Sub
La première ligne initialise la chaîne Connexion avec une valeur qui indique le type (Provider) et le nom (Data Source) de la base de données à laquelle accéder :
Connexion = ".OLEDB.4.0;Data Source=C:\\"
Remarquez le séparateur ";" entre les deux paramètres de la chaîne Connexion. Si nécessaire, vous utiliserez ce même séparateur pour préciser le nom d’utilisateur (User ID) et le mot de passe (password).
Cette chaîne est passée à l’objet OleDBConnexion ConnexionOLE pour établir la connexion avec la base de données :
ConnexionOLE.ConnectionString = Connexion
Puis un objet OleDbDataAdapter est utilisé pour accéder à la table T_TravailObjet de la base :
da = New OleDbDataAdapter("Select * from T_TravailObjet", ConnexionOLE)
Les données de la table T_TravailObjet sont placées dans un objet DataSet. Ce dernier est rempli à l’aide de la méthode Fill() :
ds = New DataSet() (ds, "mytable")
Pour que l’objet DataSet puisse être édité par l’application, il est nécessaire de le copier dans un objet DataView :
dv = ds.Tables("mytable").DefaultView
Il suffit maintenant de l’associer au contrôle DataGridView et de valider son édition :
DataGridView1.DataSource = dv dv.AllowEdit = True
Pour que tous les enregistrements de la table Catégories soient visualisés dans le contrôle DataGrid dès l’exécution de l’application, il suffit d’invoquer la procédure AfficheTous() dans Form1_Load(). Double-cliquez sur un emplacement inoccupé de la feuille et complétez la procédure Form1_Load() comme suit :
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs)
„ Handles
AfficheTous()
End Sub
La fenêtre de l’application se présente alors comme montré à la Figure 12.3.
Figure 12.3
Affichage de tous les enregistrements de la table T_TravailObjet.
Nous allons maintenant associer du code aux quatre boutons de commande de la feuille. Le bouton Bibliothèque va limiter l’affichage aux enregistrements dont le champ LibelleObjet vaut "bibliothèque". Double-cliquez sur le premier bouton et complétez la procédure Bibliothèque_Click() comme suit :
Private Sub Bibliothèque_Click(ByVal sender As System.Object, ByVal e As System.
„ EventArgs) Handles Condiments.Click
Connexion = ".OLEDB.4.0;Data Source=
„ C:\\"
ConnexionOLE.ConnectionString = Connexion
da = New OleDbDataAdapter("Select * from T_TravailObjet where [LibelleObjet]
=‘bibliothèque’", ConnexionOLE)
ds = New DataSet() (ds, "mytable")
dv = ds.Tables("mytable").DefaultView
DataGrid1.DataSource = dv dv.AllowEdit = True End Sub
Cette procédure est très proche de AfficheTous(), à ceci près que la commande d’initialisation de l’objet OleDbDataAdapter utilise une clause where pour que seuls les enregistrements dont le champ Nom de catégorie vaut Condiments soient sélectionnés :
da = New OleDbDataAdapter("Select * from T_TravailObjet where [LibelleObjet] „ =‘bibliothèque’", ConnexionOLE)
Double-cliquez sur le bouton Tous. La procédure Tous_Click() est identique à la procédure Form1_Load(). Elle se contente d’invoquer AfficheTous() afin d’afficher tous les enregistrements de la table Catégories :
Private Sub Tous_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)
„ Handles Tous.Click
AfficheTous()
End Sub
Les champs de données de la table peuvent être modifiés. Mais, attention, si vous refermez l’application, ils ne seront pas automatiquement sauvegardés dans la base de données ! Pour cela, vous devrez appeler la méthode Update(). Cette action sera effectuée en appuyant sur le bouton Mise à jour.
Double-cliquez sur ce bouton et complétez la procédure MiseAJour_Click() comme suit :
Private Sub MiseAJour_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)
„ Handles MiseAJour.Click
Connexion = ".OLEDB.4.0;Data Source=
„ C:\\"
ConnexionOLE.ConnectionString = Connexion cb = New OleDbCommandBuilder(da) da.Update(ds, "mytable") End Sub
Après avoir spécifié la base de données à utiliser :
Connexion = ".OLEDB.4.0;Data Source=C:\\"
ConnexionOLE.ConnectionString = Connexion l’objet OleDbCommandBuilder cb est créé a partir de l’objet OleDbDataAdapter da :
cb = New OleDbCommandBuilder(da)
Il suffit maintenant d’utiliser la méthode Update() pour mettre à jour la table avec le contenu de l’objet OleDbDataAdapter :
da.Update(ds, "mytable")
Pour terminer, double-cliquez sur le bouton Quitter et ajoutez une instruction End dans la procédure Quitter_Click() :
Private Sub Quitter_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)
„ Handles Quitter.Click
End
End Sub
Voici le listing complet de l’application. Les fichiers correspondants se trouvent dans le dossier db après installation des sources de l’ouvrage.
Imports
Imports .OleDb
Public Class Form1
Dim Connexion As String
Dim ConnexionOLE As OleDbConnection
Dim da As OleDbDataAdapter
Dim ds As DataSet
Dim dv As DataView
Dim cb As OleDbCommandBuilder
Public Sub AfficheTous()
Connexion = ".OLEDB.4.0;Data Source=
„ C:\\"
ConnexionOLE = New OleDbConnection
ConnexionOLE.ConnectionString = Connexion
da = New OleDbDataAdapter("Select * from T_TravailObjet", ConnexionOLE)
ds = New DataSet() (ds, "mytable")
dv = ds.Tables("mytable").DefaultView
DataGridView1.DataSource = dv dv.AllowEdit = True End Sub
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.
„ EventArgs) Handles
AfficheTous()
End Sub
Private Sub Bibliothèque_Click(ByVal sender As System.Object, ByVal e
„ As System.EventArgs) Handles Bibliothèque.Click
Connexion = ".OLEDB.4.0;Data Source=
„ C:\\"
ConnexionOLE.ConnectionString = Connexion
da = New OleDbDataAdapter("Select * from T_TravailObjet where [LibelleObjet]
„ =‘bibliothèque’", ConnexionOLE)
ds = New DataSet() (ds, "mytable")
dv = ds.Tables("mytable").DefaultView
DataGridView1.DataSource = dv dv.AllowEdit = True
End Sub
Private Sub Tous_Click(ByVal sender As System.Object, ByVal e As System.
„ EventArgs) Handles Tous.Click
AfficheTous()
End Sub
Private Sub MiseAjour_Click(ByVal sender As System.Object, ByVal e As
„ System.EventArgs) Handles MiseAjour.Click
Connexion = ".OLEDB.4.0;Data Source=
„ C:\\"
ConnexionOLE.ConnectionString = Connexion cb = New OleDbCommandBuilder(da) da.Update(ds, "mytable") End Sub
Private Sub Quitter_Click(ByVal sender As System.Object, ByVal e As System.
„ EventArgs) Handles Quitter.Click
End
End Sub
End Class
Accès à une base de données distante
Dans cette section, nous allons vous montrer comment créer une application capable d’exploiter des données contenues dans une base de données distante. Cette base a pour nom . Elle est librement téléchargeable sur la page . La technique utilisée relève des services web. Pour tous renseignements complémentaires, consultez le Chapitre 25.
Définition du service web
Lancez la commande Nouveau/Site web du menu Fichier. Sélectionnez .NET Framework 3.5 dans la liste déroulante Frameworks. Sélectionnez le modèle Service web , donnez le nom Service1 au nouveau service web et validez en cliquant sur OK. Ajoutez les clauses Imports suivantes en tête de listing :
Imports
Imports .OleDb
La clause <webservice> (devant le mot-clé Public) indique que la classe Service1 sera utilisée comme service web :
<WebService(Namespace:=";)> _
<WebServiceBinding(ConformsTo:=WsiProfiles.BasicProfile1_1)> _
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _
Public Class Service
Inherits .Services.WebService
Lorsque, par la suite, le service sera implanté sur un serveur web, vous devrez préciser son nom de domaine à la suite du mot-cléNameSpace.
Définissez les variables utilisées par le service web :
Dim Connexion As String
Dim ConnexionOLE As OleDbConnection = New OleDbConnection()
Dim da As OleDbDataAdapter
Dim ds As DataSet
Supprimez la fonction HelloWorld(), générée automatiquement par Visual Studio, et remplacez-la par la fonction AfficheTous() suivante :
<WebMethod()> Public Function AfficheTous() As DataSet
Connexion = ".OLEDB.4.0;Data Source=
„ c:\"
ConnexionOLE.ConnectionString = Connexion
da = New OleDbDataAdapter("Select * from T_TravailObjet", ConnexionOLE)
ds = New DataSet() (ds, "mytable")
Return ds
End Function
Cette fonction sera exploitée sur le Web (<WebMethod()>). Elle ne demande aucun argument ; mais renvoie un DataSet :
<WebMethod()> Public Function AfficheTous() As DataSet
Les deux lignes suivantes établissent une connexion avec la base de données. Ici, il s’agit de la base Access c:\ :
Connexion = ".OLEDB.4.0;Data Source=c:\" ConnexionOLE.ConnectionString = Connexion
Tous les enregistrements de la table T_TravailObjet sont sélectionnés et placés dans l’objet OleDbDataAdapter da :
da = New OleDbDataAdapter("Select * from T_TravailObjet", ConnexionOLE)
Puis le DataSet ds est rempli avec l’objet da :
ds = New DataSet() (ds, "mytable")
Enfin, l’objet DataSet ds est retourné par la fonction :
Return ds
Voici le code complet de la classe Service1 :
Imports
Imports .Services
Imports .Services.Protocols
Imports
Imports .OleDb
<WebService(Namespace:=";)> _
<WebServiceBinding(ConformsTo:=WsiProfiles.BasicProfile1_1)> _
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _
Public Class Service
Inherits .Services.WebService
Dim Connexion As String
Dim ConnexionOLE As OleDbConnection = New OleDbConnection()
Dim da As OleDbDataAdapter
Dim ds As DataSet
<WebMethod()> Public Function AfficheTous() As DataSet
Connexion = ".OLEDB.4.0;Data Source=
„ c:\"
ConnexionOLE.ConnectionString = Connexion
da = New OleDbDataAdapter("Select * from T_TravailObjet", ConnexionOLE) ds = New DataSet() (ds, "mytable")
Return ds
End Function
End Class
Appuyez sur la touche F5. La fonction AfficheTous() peut être testée (voir Figure 12.4).
Figure 12.4
Cette page permet de tester la fonction AfficheTous.
Cliquez sur le lien AfficheTous puis sur le bouton Appeler. Le résultat de la fonction AfficheTous() apparaît sous une forme XML (voir Figure 12.5).
Figure 12.5
Résultat de la fonction AfficheTous().
Dans la barre de notification, une icône indique que le service web est en cours d’exécution et précise le port utilisé (voir Figure 12.6).
Figure 12.6
Dans cet exemple, le service web est accessible sur le port 53946.
Ne terminez pas l’exécution du service. Nous en aurons besoin dans la section suivante.
Utilisation du service web
Vous allez maintenant définir un projet qui exploite le service web défini dans la section précédente. Ouvrez une nouvelle instance de Visual Studio et lancez la commande Nouveau > Site web du menu Fichier. Choisissez .NET Framework 3.5 dans la première liste déroulante et sélectionnez le modèle Site web . Donnez le nom TestBDDistante à l’application et validez (cette application se trouve dans le dossier Projects\TestBDDistante des sources de l’ouvrage).
Cliquez du bouton droit sur l’entrée C:\…\TestBDDistante dans l’Explorateur de solutions et choisissez Ajouter une référence web dans le menu surgissant. Saisissez l’adresse correspondant au service web en cours de débogage dans la zone URL (voir Figure 12.6).
Pour connaître le port utilisé par le service en cours de débogage, il suffit de pointer l’icône Serveur de développement dans la barre de notification (voir Figure 12.7).
Figure 12.7
L’icône Serveur de développement indique le port utilisé par le service web.
Cliquez sur le bouton Aller à. La boîte de dialogue Ajouter une référence web se présente comme montré à la Figure 12.8.
Figure 12.8
Le service Service1 est sur le point d’être intégré au projet web.
Cliquez sur Ajouter une référence. Le service web Service1 est maintenant référencé dans le projet. Vous pouvez donc utiliser sa méthode AfficheTous() (voir Figure 12.9).
Figure 12.9
Le service web Service1 est référencé dans le projet.
Ajoutez un contrôle GridView sur la page de l’application (ce contrôle se trouve sous l’onglet Données de la Boîte à outils). La fenêtre de conception se présente comme montré à la Figure 12.10.
Figure 12.10
Le contrôle GridView a été placé sur la feuille.
Pour rendre ce contrôle opérationnel, vous devez l’initialiser. Déroulez la liste Choisir la source de données et sélectionnez l’entrée <Nouvelle source de données>. Une boîte de dialogue intitulée Assistant Configuration de source de données s’affiche (voir Figure 12.11).
Figure 12.11
Cet assistant va vous aider à associer la fonction AfficheTous() au contrôle GridView.
Sélectionnez Objet dans la zone À partir d’où l’application obtiendra-t-elle les données, puis validez en cliquant sur OK. L’assistant vous demande alors de choisir un "métier" par l’intermédiaire duquel vous pourrez mettre à jour les données de la table (voir Figure 12.12).
Figure 12.12
Choix du métier localhost. Service.
Choisissez localhost.Service et cliquez sur Suivant. Vous devez maintenant choisir la méthode qui permettra de remplir l’objet GridView. Déroulez la liste et choisissez la méthode AfficheTous() (voir Figure 12.13).
Figure 12.13
La méthode AfficheTous() va permettre de remplir le GridView.
Cliquez sur Terminer. Vous pouvez vérifier que la méthode AfficheTous() du service web Service1 est bien exécutée en cliquant sur le bouton Démarrer le débogage. Une boîte de dialogue vous informe que le débogage ne peut pas être réalisé (voir Figure 12.14). Sélectionnez l’option Modifier le fichier web.config pour activer le débogage et validez en cliquant sur OK.
Figure 12.14Vous devez activer le débogage.
Au bout de quelques secondes, l’Explorateur web affiche le contenu de la table renvoyée par la méthode AfficheTous() (voir Figure 12.15).
Figure 12.15
La communication avec le service web a renvoyé les données escomptées.
Utilisation plus complète du service web
Nous allons maintenant améliorer le service web et l’application qui l’utilise pour adresser des commandes SQL à la base de données .
Ouvrez le service web Service1. Ajoutez la méthode AfficheBiblio() pour ne sélectionner que les condiments dans la table Catégories :
<WebMethod()> Public Function AfficheBiblio() As DataSet
Connexion = ".OLEDB.4.0;Data Source=
„ C:\\"
ConnexionOLE.ConnectionString = Connexion
da = New OleDbDataAdapter("Select * from T_TravailObjet where [LibelleObjet]
„ =‘bibliothèque’", ConnexionOLE)
ds = New DataSet() (ds, "mytable")
Return ds
End Function
Cette méthode est très proche de AfficheTous(), à ceci près que l’instruction de sélection des enregistrements dans la table T_TravailObjet est plus restrictive. Seuls les enregistrements dont le champ LibelleObjet a pour valeur bibliothèque sont sélectionnés :
da = New OleDbDataAdapter("Select * from T_TravailObjet where [LibelleObjet]=‘bibliothèque’", ConnexionOLE)
Définissez maintenant la méthode AfficheSQL(). Elle permettra à l’utilisateur d’interroger la base de données en entrant une requête SQL de son choix :
<WebMethod()> Public Function AfficheSQL(ByVal st As String) As DataSet
Connexion = ".OLEDB.4.0;Data Source=
„ C:\\"
ConnexionOLE.ConnectionString = Connexion da = New OleDbDataAdapter(st, ConnexionOLE)
ds = New DataSet() (ds, "mytable")
Return ds
End Function
Remarquez la définition de la fonction AfficheSQL(). Celle-ci admet un argument String et retourne un DataSet :
<WebMethod()> Public Function AfficheSQL(ByVal st As String) As DataSet
La chaîne st passée en argument de la fonction est utilisée pour sélectionner les enregistrements dans l’objet da :
da = New OleDbDataAdapter(st, ConnexionOLE)
Voici le code complet du service web Service1. Ce code, ainsi que les fichiers complémentaires au projet, se trouvent dans le dossier Service1 après installation des sources de l’ouvrage.
Imports
Imports .Services
Imports .Services.Protocols
Imports
Imports .OleDb
<WebService(Namespace:=";)> _
<WebServiceBinding(ConformsTo:=WsiProfiles.BasicProfile1_1)> _
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _
Public Class Service
Inherits .Services.WebService
Dim Connexion As String
Dim ConnexionOLE As OleDbConnection = New OleDbConnection()
Dim da As OleDbDataAdapter
Dim ds As DataSet
<WebMethod()> Public Function AfficheTous() As DataSet
Connexion = ".OLEDB.4.0;Data Source=
„ c:\"
ConnexionOLE.ConnectionString = Connexion
da = New OleDbDataAdapter("Select * from T_TravailObjet", ConnexionOLE)
ds = New DataSet() (ds, "mytable")
Return ds
End Function
<WebMethod()> Public Function AfficheBiblio() As DataSet
Connexion = ".OLEDB.4.0;Data Source=
„ C:\\"
ConnexionOLE.ConnectionString = Connexion
da = New OleDbDataAdapter("Select * from T_TravailObjet where [LibelleObjet]
„ =‘bibliothèque’", ConnexionOLE)
ds = New DataSet() (ds, "mytable")
Return ds
End Function
<WebMethod()> Public Function AfficheSQL(ByVal st As String) As DataSet
Connexion = ".OLEDB.4.0;Data Source=
„ C:\\"
ConnexionOLE.ConnectionString = Connexion
da = New OleDbDataAdapter(st, ConnexionOLE)
ds = New DataSet() (ds, "mytable")
Return ds
End Function
End Class
Cliquez sur le bouton Démarrer le débogage pour lancer le service web. Une icône dans la barre de notification indique que le service web est actif (voir Figure 12.16) et une page web signale que trois méthodes sont accessibles dans le service (voir Figure 12.17).
Figure 12.16
Dans cet exemple, le service web est accessible sur le port 1202.
Figure 12.17Les trois méthodes du service web.
Vous allez maintenant définir une application qui utilise les trois méthodes du service web précédent. Ouvrez une nouvelle instance de Visual Studio et lancez la commande Nouveau/Site web du menu Fichier. Choisissez .NET Framework 3.5 dans la première liste déroulante, sélectionnez le modèle Site Web , donnez le nom TestBDDistante2 à l’application et validez.
Une fois que l’interface de l’application a été créée par Visual , cliquez du bouton droit sur l’entrée C:\…\TestBDDistante2 dans l’Explorateur de solutions et sélectionnez Ajouter une référence web dans le menu surgissant. Entrez l’adresse correspondant au service web local créé précédemment dans la zone URL de la boîte de dialogue Ajouter une référence web et validez en cliquant sur Aller à.
Quelques instants plus tard, les méthodes AfficheBiblio(), AfficheSQL() et AfficheTous() proposées par le service sont référencées dans la boîte de dialogue Ajouter une référence web (voir Figure 12.18).
Figure 12.18
Service1 donne accès à trois méthodes.
Cliquez sur Ajouter une référence. L’Explorateur de solutions laisse apparaître le nouveau service (voir Figure 12.19).
Figure 12.19
Le nouveau service est bien référencé dans l’application.
En utilisant l’onglet Standard de la Boîte à outils, ajoutez trois boutons de commande et une zone de texte à la feuille de l’application. Modifiez les propriétés de ces contrôles comme indiqué dans le tableau suivant :
| Contrôle | Propriété | Valeur |
| Button1 | Text | Affiche tous |
| Button2 | Text | Affiche bibliothèques |
| Button3 | Text | Exécute SQL |
| TextBox1 | Text |
Sélectionnez l’onglet Données dans la Boîte à outils et déposez un contrôle GridView sur la feuille de l’application. Une boîte de dialogue vous invite à définir la source des données à afficher. Appuyez sur la touche Échap du clavier : la définition de ce contrôle se fera dans le code.
La fenêtre de conception doit à présent avoir l’allure de la Figure 12.20.
Figure 12.20La feuille de l’application, en mode Édition.
Double-cliquez sur une partie non occupée de la feuille de l’application et complétez la procédure Page_Load() comme suit :
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs)
„ Handles
Dim objds As New localhost.Service
Dim ds As DataSet ds = objds.AfficheTous GridView1.DataSource = ds
GridView1.DataBind()
End Sub
La première instruction donne accès au service web Service au travers de l’objet objds :
Dim objds As New localhost.Service
Après avoir défini un objet DataSet ds, cet objet est initialisé grâce à la fonction AfficheTous du service web :
Dim ds As DataSet ds = objds.AfficheTous
Il suffit maintenant de remplir le GridView de la feuille avec le DataSet ds :
GridView1.DataSource = ds.Tables(0).DefaultView
GridView1.DataBind()
Pour pouvoir définir l’objet DataSet ds, vous devez insérer une instruction Imports au début du code :
Imports
Il ne reste plus qu’à donner vie aux boutons de commande et à la zone de texte pour terminer l’application. Fermez la fenêtre du navigateur pour revenir à l’environnement de développement.
Double-cliquez sur le premier bouton de commande et complétez la procédure Button1_ Click() comme suit :
Protected Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs)
„ Handles Button1.Click
Dim objds As New localhost.Service
Dim ds As DataSet ds = objds.AfficheTous GridView1.DataSource = ds
GridView1.DataBind()
End Sub
Les instructions de cette procédure sont les mêmes que celles exécutées au démarrage de l’application. Elles affichent donc la totalité des enregistrements de la table.
Double-cliquez sur le deuxième bouton de commande et complétez la procédure Button2_ Click() comme suit :
Protected Sub Button2_Click(ByVal sender As Object, ByVal e As System.EventArgs)
„ Handles Button2.Click
Dim objds As New localhost.Service
Dim ds As DataSet ds = objds.AfficheBiblio
GridView1.DataSource = ds.Tables(0).DefaultView
GridView1.DataBind()
End Sub
Cette procédure est analogue à Button1_Click(), à ceci près que le DataSet est initialisé avec la fonction web AfficheBiblio() :
ds = objds.AfficheBiblio
Enfin, double-cliquez sur le troisième bouton de commande et complétez la procédure Button3_Click() comme suit :
Protected Sub Button3_Click(ByVal sender As Object, ByVal e As System.EventArgs)
„ Handles Button3.Click
Dim objds As New localhost.Service
Dim ds As DataSet
ds = objds.AfficheSQL()
GridView1.DataSource = ds.Tables(0).DefaultView
GridView1.DataBind()
End Sub
Cette procédure est analogue aux deux précédentes, mais elle remplit le contrôle DataSet ds en interrogeant la fonction AfficheSQL() (l’argument fourni à la fonction AfficheSQL() est le contenu du TextBox) :
ds = objds.AfficheSQL()
Voici le listing complet de l’application. Vous le trouverez, ainsi que les fichiers complémentaires, dans le dossier TestBDDistante2.
Imports
Partial Class _Default
Inherits
Protected Sub Button1_Click(ByVal sender As Object, ByVal e As System.
„ EventArgs) Handles Button1.Click
Dim objds As New localhost.Service
Dim ds As DataSet ds = objds.AfficheTous GridView1.DataSource = ds
GridView1.DataBind()
End Sub
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs)
„ Handles
Dim objds As New localhost.Service
Dim ds As DataSet ds = objds.AfficheTous GridView1.DataSource = ds
GridView1.DataBind()
End Sub
Protected Sub Button2_Click(ByVal sender As Object, ByVal e As System.
„ EventArgs) Handles Button2.Click
Dim objds As New localhost.Service
Dim ds As DataSet ds = objds.AfficheBiblio
GridView1.DataSource = ds.Tables(0).DefaultView
GridView1.DataBind()
End Sub
Protected Sub Button3_Click(ByVal sender As Object, ByVal e As System.
„ EventArgs) Handles Button3.Click
Dim objds As New localhost.Service
Dim ds As DataSet
ds = objds.AfficheSQL()
GridView1.DataSource = ds.Tables(0).DefaultView
GridView1.DataBind()
End Sub
End Class
Appuyez sur la touche F5 pour exécuter l’application. Les Figures 12.21, 12.22 et 12.23 représentent le formulaire web après avoir appuyé (respectivement) sur les boutons Affiche tous, Affiche Bibliothèques et Exécute SQL. Dans le dernier cas, la requête SQL exécutée était la suivante :
select * from T_TravailObjet where [IdTravail]=29
Figure 12.21
Tous les enregistrements de la table Catégories s’affichent.
Figure 12.22
Seuls les enregistrements dont le champ LibelleObjet vaut «bibliothèque» s’affichent.
Figure 12.23
Seuls les enregistrements correspondant à la requête SQL apparaissent.
Accès à une base de données via LINQ
Les bases de données , SQL Server et SQL Server Express peuvent être accédées par l’intermédiaire de requêtes LINQ.
Voici, à titre d’exemple une requête permettant de sélectionner des enregistrements dans une table d’une base de données :
Dim objets As DataTable = ds.Tables("T_TravailObjet")
Dim query = _
From objet In objets.AsEnumerable() _
Where objet.Field(Of String)("LibelleObjet") = "bibliothèque" _
Select New With { _
.IDTravailObjet = objet.Field(Of Integer)("IDTravailObjet"), _
.IDTravail = objet.Field(Of Integer)("IDTravail"), _
.Nombre = objet.Field(Of Integer)("Nombre")
}
Cette requête crée un iEnumerable contenant les données IDTravailObjet, IDTravail et Nombre. Ces données proviennent des champs IDTravailObjet, IDTravail et Nombre de la table T_TravailObjet. Seuls les enregistrements dont le champ LibelleObjet vaut "Bibliothèque" sont sélectionnés par la requête.
Vous vous reporterez à la section intitulée "LINQ to DataSet", au Chapitre 27 pour avoir des informations complémentaire sur l’interrogation de bases de données . Dans cet autre exemple, la table interrogée est de type SQL Server :
Dim query = From orde In db.Orders
Order By orde.CustomerID
Select orde.CustomerID, orde.OrderID
La requête LINQ extrait les champs CustomerID et OrderID de la table Orders et les classe par ordre croissant sur le champ CustomerID.
Pour avoir des informations complémentaires concernant le requêtage LINQ des bases de données SQL Server et SQL Server Express, vous consulterez la section intitulée "LINQ to SQL" au Chapitre 27.
13
Traitements multitâches/ multicœurs
Il y a quelques années, on mesurait la puissance de calcul brut d’un ordinateur à la fréquence de son microprocesseur. Aujourd’hui, cette fréquence se situe la plupart du temps autour des 3 GHz. En l’état actuel de la technologie, cette barrière a du mal à être franchie, essentiellement pour des raisons de dissipation thermique. Pour augmenter la puissance de calcul, les fondeurs ont eu l’idée de loger plusieurs puces (ou cœurs) dans un même chip. Cette solution, fort prometteuse, n’est encore qu’assez mal utilisée par les éditeurs de logiciels qui, bien souvent, se contentent d’utiliser des instructions traditionnelles, de type monocœur. Heureusement, avec Visual Basic 2010, la mise en place d’un traitement multitâches/ multicœurs est un vrai jeu d’enfant. Cette facilité de mise en œuvre découle de plusieurs techniques :
? Le composant BackgroundWorker : grâce à lui, un traitement consommateur de temps machine peut être implémenté dans un thread qui s’exécutera en tâche de fond. Cela évite de "geler" la machine si un long calcul doit être effectué, et le programme donne une impression de fluidité à ses utilisateurs.
? Le .NET Framework 4 fournit de nouvelles bibliothèques de classes. En particulier, la classe Parallel qui permet de répartir l’exécution de boucles For et For Each sur les différents cœurs disponibles.
? Le concept de tâches, lié à la classe Task, permet de gérer finement l’exécution de code par les différents cœurs disponibles.
Deux applications illustrent le composant BackgroundWorker sont développées dans ce chapitre. La première montre comment effectuer un calcul "lourd" en tâche de fond. La seconde propose deux techniques pour exécuter une application externe : en tâche de fond ou en tâche principale.
Deux applications illustrent l’utilisation de l’instruction et montrent sa supériorité par rapport à une classique structure For Next.
Enfin, une application montre comment affecter l’exécution de blocs de code à certains cœurs du processeur utilisé. Les instructions de cette application n’ont aucune incidence sur un processeur doté d’un seul cœur.
Exécution d’un calcul en tâche de fond
Cette première application va calculer une factorielle en tâche de fond. Lancez commande Nouveau/Projet du menu Fichier. Choisissez .NET Framework 4 dans la liste déroulante Framework. Sélectionnez Visual Basic/Windows dans le volet gauche et Application Windows Forms dans le volet central. Donnez le nom Multitâche au projet et cliquez sur
OK. Ajoutez deux Label, un TextBox, deux Button, un ProgressBar et un BackgroundWorker (ce contrôle se trouve sous l’onglet Composants de la Boîte à outils) pour obtenir l’effet visuel de la Figure 13.1.
Figure 13.1
Agencement de l’application de traitement multitâche.
Modifiez les propriétés de ces contrôles comme indiqué dans le tableau suivant :
| Contrôle | Propriété | Valeur |
| Form1 | Text | Traitement multitâche |
| Label1 | Text | Entrez un nombre |
| TextBox1 | Text | 20 |
| Button1 | Text | Calculer |
| Button2 | Text | Arrêter |
| Label2 | Text | Entrez un nombre et cliquez sur Calculer |
| BackgroundWorker1 | Name | bgw |
| BackgroundWorker1 | WorkerReportsProgress | True |
Double-cliquez sur le bouton Calculer et complétez la procédure Button1_Click() comme suit :
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)
„ Handles Button1.Click
If CInt() > 20 Or CInt() < 1 Then
MsgBox("Le nombre doit être compris entre 1 et 20")
Else
= "Calcul en cours "
Button1.Enabled = False
bgw.RunWorkerAsync(CInt())
End If
End Sub
La première instruction teste la valeur entrée par l’utilisateur dans la zone de texte. Pour éviter un dépassement dans le calcul de la factorielle, cette valeur doit être comprise entre 1 et 20. Dans le cas contraire, un message d’erreur apparaît :
If CInt() > 20 Or CInt() < 1 Then
MsgBox("Le nombre doit être compris entre 1 et 20")
Si la valeur entrée est comprise entre 1 et 20, trois actions sont effectuées. Dans un premier temps, un message s’affiche dans la fenêtre par l’intermédiaire du contrôle Label2 :
Else
= "Calcul en cours "
Dans un deuxième temps, le bouton Calculer est désactivé pour éviter que l’utilisateur n’appuie dessus avant la fin du calcul :
Button1.Enabled = False
Enfin, dans un troisième temps, le processus asynchrone démarre :
bgw.RunWorkerAsync(CInt())
Cette dernière instruction génère un événement Dowork rattaché à l’objet BackgroundWorker bgw. Nous allons donc définir la procédure événementielle bgw_Dowork(). Cliquez sur l’icône bgw (en dessous de la fenêtre de l’application), affichez les événements dans la fenêtre des propriétés et double-cliquez sur la propriété DoWork pour accéder à la procédure bgw_DoWork(). Complétez cette procédure comme suit :
Private Sub bgw_DoWork(ByVal sender As System.Object, ByVal e As System.
„ ComponentModel.DoWorkEventArgs) Handles bgw.DoWork
Dim worker As BackgroundWorker = CType(sender, BackgroundWorker)
e.Result = factorielle(e.Argument, worker, e) End Sub
La première instruction récupère l’objet BackgroundWorker à l’origine de cet événement :
Dim worker As BackgroundWorker = CType(sender, BackgroundWorker)
La seconde instruction appelle la fonction Factorielle() et stocke la valeur renvoyée dans la propriété Result de l’objet DoWorkEventArgs :
e.Result = factorielle(e.Argument, worker, e)
L’étape suivante consiste à définir la fonction Factorielle() :
Function factorielle(ByVal n As Integer, ByVal worker As BackgroundWorker,
„ ByVal e As DoWorkEventArgs) As Long
Dim i As Long
Dim percentcomplete As Integer
resultat = 1 For i = 1 To n resultat = i * resultat
percentcomplete = CSng(i) / CSng(n) * 100 worker.ReportProgress(percentcomplete)
System.Threading.Thread.Sleep(150)
Next (i)
Return resultat
End Function
Après avoir déclaré l’index de la boucle de calcul, la variable représentant l’état d’avancement dans le calcul et la variable dans laquelle le résultat va être stocké :
Dim i As Long
Dim percentcomplete As Integer
resultat = 1
le calcul récursif de la factorielle prend place :
For i = 1 To n resultat = i * resultat
percentcomplete = CSng(i) / CSng(n) * 100 worker.ReportProgress(percentcomplete)
System.Threading.Thread.Sleep(150)
Next (i)
Remarquez les deux dernières instructions de la boucle :
? worker.ReportProgress(percentcomplete) affiche l’état d’avancement du calcul. Cette instruction va déclencher l’événement ProgressChanged de l’objet BackgroundWorker.
? System.Threading.Thread.Sleep(150) introduit une pause de 150 millisecondes entre chacune des étapes du calcul. Cela évite un avancement trop rapide de la barre de progression.
L’étape suivante consiste à définir la procédure événementielle bgw_ProgressChanged(). Cliquez sur l’icône bgw (en dessous de la fenêtre de l’application), affichez les événements dans la fenêtre des propriétés et double-cliquez sur la propriété ProgressChanged pour accéder à la procédure bgw_ProgressChanged(). Complétez cette procédure comme suit :
Private Sub bgw_ProgressChanged(ByVal sender As System.Object, ByVal e As
„ System.ComponentModel.ProgressChangedEventArgs) Handles bgw.ProgressChanged
Me.ProgressBar1.Value = e. Private Sub bgw_ProgressChanged(ByVal sender
„ As System.Object, ByVal e As System.ComponentModel.ProgressChangedEventArgs)
„ Handles bgw.ProgressChanged
Me.ProgressBar1.Value = e.ProgressPercentage
End Sub
End Sub
L’unique instruction de cette procédure met à jour la barre de progression en utilisant la variable ProgressPercentage.
Nous allons maintenant définir la procédure à exécuter en fin de calcul. Cliquez sur l’icône bgw (en dessous de la fenêtre de l’application), affichez les événements dans la fenêtre des propriétés et double-cliquez sur la propriété RunWorkerCompleted pour accéder à la procédure bgw_ RunWorkerCompleted(). Complétez cette procédure comme suit :
Private Sub bgw_RunWorkerCompleted(ByVal sender As System.Object, ByVal e As
„ System.ComponentModel.RunWorkerCompletedEventArgs) Handles bgw.RunWorkerCompleted
Button1.Enabled = True
= "Factorielle(" + + ") = " + Str(resultat)
End Sub
Cette procédure active à nouveau le bouton Calculer et affiche le résultat du calcul dans le contrôle Label2.
Pour terminer, double-cliquez sur le bouton Arrêter et ajoutez une instruction End dans la procédure Button2_Click :
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)
„ Handles Button2.Click
End
End Sub
L’application est maintenant totalement opérationnelle. Vous pouvez l’exécuter en appuyant sur la touche F5. Entrez un nombre compris entre 1 et 20 dans la zone de texte et cliquez sur le bouton Calculer. Vous pouvez voir l’avancement de la barre de progression – en ayant bien en tête que les calculs sont effectués dans un thread autre que celui de l’application (voir Figure 13.2).
Figure 13.2
L’application Traitement multitâche en cours d’exécution.
Voici le code complet de l’application. Vous trouverez les fichiers correspondants dans le dossier multitâche.
Imports System.ComponentModel
Public Class Form1
Dim longueur As Integer = 0
Dim resultat As Long = 0
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.
„ EventArgs) Handles Button1.Click
If CInt() > 20 Or CInt() < 1 Then
MsgBox("Le nombre doit être compris entre 1 et 20")
Else
= "Calcul en cours "
Button1.Enabled = False
bgw.RunWorkerAsync(CInt())
End If
End Sub
Private Sub bgw_DoWork(ByVal sender As System.Object, ByVal e As System.
„ ComponentModel.DoWorkEventArgs) Handles bgw.DoWork
Dim worker As BackgroundWorker = CType(sender, BackgroundWorker)
e.Result = factorielle(e.Argument, worker, e)
End Sub
Function factorielle(ByVal n As Integer, ByVal worker As BackgroundWorker,
„ ByVal e As DoWorkEventArgs) As Long
Dim i As Long
Dim percentcomplete As Integer resultat = 1 For i = 1 To n resultat = i * resultat percentcomplete = CSng(i) / CSng(n) * 100 worker.ReportProgress(percentcomplete)
System.Threading.Thread.Sleep(150)
Next (i)
Return resultat
End Function
Private Sub bgw_ProgressChanged(ByVal sender As System.Object, ByVal e As
„ System.ComponentModel.ProgressChangedEventArgs) Handles bgw.ProgressChanged
Me.ProgressBar1.Value = e.ProgressPercentage
End Sub
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.
„ EventArgs) Handles Button2.Click
End
End Sub
Private Sub bgw_RunWorkerCompleted(ByVal sender As System.Object, ByVal
„ e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles bgw.
„ RunWorkerCompleted
Button1.Enabled = True
= "Factorielle(" + + ") = " + Str(resultat)
End Sub
End Class
Exécution d’une application externe
Il est parfois utile d’appeler une application exécutable dans un projet Visual Basic. La technique à utiliser diffère selon que vous vouliez lancer l’application en tant que processus ou attendre sa fermeture pour reprendre le contrôle.
Définissez un nouveau projet fondé sur le modèle Application Windows Forms et donnezlui le nom LanceBN. Insérez un TextBox et deux Button sur la feuille du projet. Modifiez les propriétés de ces contrôles comme indiqué dans le tableau suivant :
| Contrôle | Propriété | Valeur |
| Form1 | Text | Lanceur d’applications |
| TextBox1 | Text | |
| Button1 | Text | Lancer |
| Button2 | Text | Lancer et attendre |
Modifiez l’emplacement et les dimensions de ces contrôles de sorte que la feuille de l’application ressemble à la Figure 13.3.
Figure 13.3
La feuille de l’application, en mode Édition.
Double-cliquez sur le bouton Lancer et complétez la procédure Button1_Click() comme suit :
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)
„ Handles Button1.Click
Process.Start()
("L’application a été lancée", "Information")
End Sub
La classe Process permet de démarrer des applications en tant que processus, donc sans bloquer le programme qui les active. Consultez la documentation en ligne pour connaître les nombreuses méthodes de cette classe.
La première instruction lance le processus dont le nom est spécifié dans la zone de texte TextBox1 :
Process.Start()
La seconde instruction affiche une boîte de message indiquant que l’application a été lancée. Étant donné que le lancement d’un processus ne bloque pas l’ordinateur, cette boîte de message apparaît immédiatement :
("L’application a été lancée", "Information")
Double-cliquez sur le bouton Lancer et attendre, et complétez la procédure Button2_ Click() comme suit :
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)
„ Handles Button2.Click
Shell(, AppWinStyle.NormalFocus, True)
("L’application vient d’être fermée", "Information")
End Sub
La première instruction utilise la procédure Shell() pour lancer l’application spécifiée dans la zone de texte :
Shell(, AppWinStyle.NormalFocus, True)
Le premier argument de la procédure précise le nom de l’application à lancer. Ce nom doit être un chemin complet si l’application ne se trouve pas dans le dossier d’installation de Windows ou dans le dossier système.
Le deuxième argument indique l’état de l’application. Il peut être égal à l’une des valeurs suivantes :
| ? | . Fenêtre cachée ayant le focus. |
| ? | AppWinStyle.NormalFocus. Fenêtre normale ayant le focus. |
| ? | AppWinStyle.MinimizedFocus. Fenêtre minimisée dans la barre des tâches ayant le focus. |
| ? | AppWinStyle.MaximizedFocus. Fenêtre ouverte et maximisée. |
| ? | AppWinStyle.NormalNoFocus. Fenêtre normale n’ayant pas le focus. |
| ? | AppWinStyle.MinimizedNoFocus. Fenêtre minimisée dans la barre des tâches n’ayant pas le focus. |
Enfin, le troisième argument indique si le programme parent Visual Basic doit attendre (True) ou ne pas attendre (False) la fin de l’application lancée pour poursuivre son exécution. Si ce paramètre n’est pas spécifié, la fin de l’application n’est pas attendue.
La deuxième instruction affiche un message qui précise que l’application vient d’être fermée. Ce message ne s’affiche qu’après la fermeture de l’application, car le troisième paramètre de la fonction Shell() vaut True :
("L’application vient d’être fermée", "Information")
Lorsque l’instructionShell ne contient que deux paramètres, l’application est lancée et le contrôle est immédiatement redonné à l’instruction suivante. Ce comportement fait ressembler la procédureShell() au démarrage d’un processus. Cependant, les possibilités des processus sont bien plus nombreuses. Pour en savoir plus à ce sujet, consultez la documentation de Visual Basic.
Voici le listing complet de l’application. Le projet se trouve dans le dossier LanceBN après installation des sources de l’ouvrage.
Public Class Form1
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.
„ EventArgs) Handles Button1.Click
Process.Start()
("L’application a été lancée", "Information")
End Sub
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.
„ EventArgs) Handles Button2.Click
Shell(, AppWinStyle.NormalFocus, True)
("L’application vient d’être fermée", "Information")
End Sub
End
Parallélisation des boucles
La classe Parallel du .NET Framework 4 permet de répartir l’exécution de boucles For et For Each sur les différents cœurs disponibles. Pour illustrer cette classe, nous allons développer une application console qui calcule un million de racines carrées, dans un premier temps à l’aide d’une boucle For Next conventionnelle, puis à l’aide d’une boucle Parallel. For. Les temps de calcul s’afficheront à la suite des deux variantes du code.
Lancez la commande Nouveau/Projet dans le menu Fichier. Sélectionnez .NET Framework 4 dans la liste déroulante Framework. Sélectionnez Visual Basic/Windows dans le volet gauche. Cliquez sur Application console, donnez le nom ParallelFor1 à l’application et validez en cliquant sur OK. Complétez le code avec les instructions suivantes (cette application se trouve dans le dossier Projects\ParallelFor1 des sources de l’ouvrage après leur installation).
Imports System.Threading
Imports System.Threading.Tasks
Module Module1
Function Calcul(ByVal i As Integer, ByVal result As String) As Boolean
result = "Racine carrée : " + (i).ToString()
Return True
End Function
Sub Main()
Dim result As String
Dim debut As TimeSpan
Console.WriteLine("Début du calcul simple thread")
debut = .TimeOfDay
For i = 0 To 10000000
Calcul(i,result)
Next
Console.WriteLine("Fin du calcul simple thread")
Console.WriteLine(.TimeOfDay - debut)
Console.WriteLine()
Console.WriteLine("Début du calcul multithread")
debut = .TimeOfDay
(0, 10000000, Function(i) Calcul(i, result))
Console.WriteLine("Fin du calcul multithread")
Console.WriteLine(.TimeOfDay - debut)
Console.ReadKey()
End Sub
End Module
Examinons le code.
Après avoir déclaré les deux espaces de noms nécessaires à l’exécution multithreads :
Imports System.Threading
Imports System.Threading.Tasks
Le bloc de code suivant définit la fonction Calcul(), responsable du calcul des 1 million de racines carrées :
Function Calcul(ByVal i As Integer, ByVal result As String) As Boolean
result = "Racine carrée : " + (i).ToString()
Return True
End Function
La procédure Main() se décompose en quatre blocs.
Le premier bloc définit les variables utilisées dans la procédure :
Dim result As String
Dim debut As TimeSpan
Le deuxième bloc effectue une boucle For Next traditionnelle qui appelle la fonction Calcul() 1 million de fois. Après avoir affiché un message pour indiquer le début du calcul :
Console.WriteLine("Début du calcul simple thread") L’heure système est mémorisée dans la variable debut :
debut = .TimeOfDay Puis le calcul est lancé :
For i = 0 To 10000000
Calcul(i,result)
Next
Lorsque la boucle For Next est terminée, une instruction WriteLine indique la fin du calcul :
Console.WriteLine("Fin du calcul simple thread")
Et une autre affiche le temps nécessaire pour effectuer le calcul :
Console.WriteLine(.TimeOfDay - debut)
Le troisième bloc d’instructions effectue le même calcul en mode multithreads. Après avoir indiqué le début du calcul et mémorisé l’heure système :
Console.WriteLine("Début du calcul multithread") debut = .TimeOfDay
La fonction Calcul() est appelée un million de fois :
(0, 10000000, Function(i) Calcul(i, result))
Remarquez la syntaxe particulière de cette instruction. Les deux premiers paramètres font référence aux valeurs minimale et maximale de l’index. Le troisième paramètre spécifie la fonction à exécuter et les paramètres qui doivent lui être passés.
Lorsque l’exécution de l’instruction est terminée, un message apparaît dans la console, accompagné du temps de calcul :
Console.WriteLine("Fin du calcul multithread")
Console.WriteLine(.TimeOfDay - debut)
La dernière instruction attend que l’utilisateur appuie sur une touche du clavier pour mettre fin au programme :
Console.ReadKey()
La Figure 13.4 représente le résultat de ce programme exécuté sur un AMD Phenom 9850 cadencé à 2,5 GHz, doté de 3 Go de RAM DDR2 et fonctionnant sous Windows 7 32 bits.
Figure 13.4
Le traitement parallèle est effectivement plus rapide sur un multicœur.
Les Figures 13.5 et 13.6 représentent les deux phases d’exécution du programme.
Figure 13.5
Le deuxième cœur est utilisé pour effectuer le calcul.
Figure 13.6
Les quatre cœurs effectuent le calcul, améliorant ainsi les performances.
Voici un deuxième exemple qui met en évidence la supériorité de la programmation parallèle lorsqu’il est exécuté sur un ordinateur muni de plusieurs cœurs. Ce code est issu de la librairie en ligne MSDN, page aspx. Il consiste en la multiplication de matrices de 180 colonnes et 2 000 lignes. Vous trouverez plusieurs autres exemples de programmation parallèle sur cette page. N’hésitez pas à vous y reporter.
Lancez la commande Nouveau/Projet dans le menu Fichier. Sélectionnez .NET Framework 4 dans la liste déroulante Framework, cliquez sur Application console, donnez le nom ParallelFor2 à l’application et validez en cliquant sur OK. Complétez le code avec les instructions suivantes (cette application se trouve dans le dossier Projects\ParallelFor2 des sources de l’ouvrage après leur installation) :
Imports System.Threading.Tasks
Module Module1
Sub MultiplyMatricesSequential(ByVal matA As Double(,), ByVal matB As Double(,),
„ ByVal result As Double(,))
Dim matACols As Integer = matA.GetLength(1)
Dim matBCols As Integer = matB.GetLength(1)
Dim matARows As Integer = matA.GetLength(0)
For i As Integer = 0 To matARows - 1
For j As Integer = 0 To matBCols - 1
