Notes
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de modifier des répertoires.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de modifier des répertoires.
Visual Studio fournit plusieurs outils et éléments d’interface utilisateur pour vous aider à déboguer des applications multithreads. Ce tutoriel montre comment utiliser les marqueurs de thread, la fenêtre Piles parallèles, la fenêtre Espion parallèle, les points d’arrêt conditionnels et les points d’arrêt de filtre. Vous vous familiarisez ainsi avec les fonctionnalités de débogage d’applications multithread de Visual Studio.
Les deux articles fournissent des informations supplémentaires sur le recours à d’autres outils de débogage multithread :
Pour utiliser la barre d’outils Emplacement de débogage et la fenêtre Threads, consultez Procédure pas à pas : Débogage d’une application multithread.
Pour obtenir un exemple qui utilise Task (code managé) et le runtime d’accès concurrentiel (C++), consultez Procédure pas à pas : déboguer une application parallèle. Pour obtenir des conseils de débogage généraux qui s’appliquent à la plupart des types d’applications multithreads, lisez cet article et celui-ci.
La première étape consiste à créer un projet d’application multi-tâches.
Création d’un projet d’application multithread
Ouvrez Visual Studio et créez un projet.
Si la fenêtre de démarrage n’est pas ouverte, choisissez Fichier>fenêtre de démarrage.
Dans la fenêtre de démarrage, choisissez Créer un projet.
Dans la fenêtre Créer un projet , entrez ou tapez la console dans la zone de recherche. Ensuite, choisissez C#, C++ ou Visual Basic dans la liste de langues, puis choisissez Windows dans la liste plateforme.
Après avoir appliqué les filtres de langue et de plateforme, choisissez le modèle d’application console pour .NET ou C++, puis choisissez Suivant.
Remarque
Si vous ne voyez pas le modèle approprié, accédez à ToolsGet Tools >and Features..., qui ouvre Visual Studio Installer. Choisissez le développement de bureau .NET ou le développement Desktop avec la charge de travail C++ , puis choisissez Modifier.
Dans la fenêtre Configurer votre nouveau projet , tapez ou entrez MyThreadWalkthroughApp dans la zone Nom du projet . Ensuite, choisissez Suivant ou Créer, selon l’option disponible.
Pour un projet .NET Core ou .NET 5+, choisissez le framework cible recommandé ou .NET 8, puis choisissez Créer.
Un nouveau projet console s'affiche. Une fois le projet créé, un fichier source s’affiche. Selon la langue que vous avez choisie, le fichier source peut être appelé Program.cs, MyThreadWalkthroughApp.cpp ou Module1.vb.
Supprimez le code qui apparaît dans le fichier source et remplacez-le par le code mis à jour suivant. Choisissez l’extrait de code approprié pour votre configuration de code.
using System; using System.Threading; public class ServerClass { static int count = 0; // The method that will be called when the thread is started. public void InstanceMethod() { Console.WriteLine( "ServerClass.InstanceMethod is running on another thread."); int data = count++; // Pause for a moment to provide a delay to make // threads more apparent. Thread.Sleep(3000); Console.WriteLine( "The instance method called by the worker thread has ended. " + data); } } public class Simple { public static void Main() { for (int i = 0; i < 10; i++) { CreateThreads(); } } public static void CreateThreads() { ServerClass serverObject = new ServerClass(); Thread InstanceCaller = new Thread(new ThreadStart(serverObject.InstanceMethod)); // Start the thread. InstanceCaller.Start(); Console.WriteLine("The Main() thread calls this after " + "starting the new InstanceCaller thread."); } }
Dans le menu Fichier, sélectionnez Enregistrer tout.
(Visual Basic uniquement) Dans l’Explorateur de solutions (volet droit), cliquez avec le bouton droit sur le nœud du projet, choisissez Propriétés. Sous l’onglet Application , remplacez l’objet Startup par Simple.
Déboguer l’application multi-threadée
Dans l’éditeur de code source, recherchez l’extrait de code suivant :
Cliquez avec le bouton gauche dans la barre gauche de l’instruction
Thread.Sleep
ou, pour C++,std::this_thread::sleep_for
pour insérer un nouveau point d’arrêt.Dans la gouttière, un cercle rouge indique qu’un point d’arrêt est défini à cet emplacement.
Dans le menu Débogage , sélectionnez Démarrer le débogage (F5).
Visual Studio génère la solution, l’application commence à s’exécuter avec le débogueur attaché, puis l’application s’arrête au point d’arrêt.
Dans l’éditeur de code source, recherchez la ligne qui contient le point d’arrêt.
Découvrir le marqueur de fil
Dans la barre d’outils de débogage, sélectionnez le bouton Afficher les threads dans la source
.
Appuyez deux fois sur F11 pour faire avancer le débogueur.
Regardez la gouttière sur le côté gauche de la fenêtre. Sur cette ligne, notez une icône de marqueur de thread
qui ressemble à deux fils tordus. Le marqueur de thread indique qu’un thread est arrêté à cet emplacement.
Un marqueur de thread peut être partiellement masqué par un point d’arrêt.
Survolez le pointeur sur le marqueur de fil. Un conseil sur les données apparaît, indiquant le nom et le numéro d’ID de chacun des threads arrêtés. Dans ce cas, le nom est probablement
<noname>
.Sélectionnez le marqueur de thread pour afficher les options disponibles dans le menu contextuel.
Afficher les emplacements des threads
Dans la fenêtre Stacks parallèles, vous pouvez basculer entre une vue Threads et une vue Tâches (pour la programmation basée sur des tâches) et afficher les informations de pile des appels pour chaque thread. Dans cette application, nous pouvons utiliser la vue Threads.
Ouvrez la fenêtre Piles parallèles en choisissant Déboguer>Windows>Piles parallèles. Vous devriez voir quelque chose de similaire à ce qui suit. Les informations exactes peuvent varier en fonction de l’emplacement actuel de chaque thread, de votre matériel et de votre langage de programmation.
Dans cet exemple, de gauche à droite, nous voyons ces informations pour le code managé :
- Le thread actuel (flèche jaune) est entré en
ServerClass.InstanceMethod
. Vous pouvez afficher l’ID de thread et le cadre de pile d’un thread en pointant surServerClass.InstanceMethod
. - Thread 31724 attend un verrou appartenant à Thread 20272.
- Le thread principal (côté gauche) s’est arrêté sur [Code externe], que vous pouvez afficher en détail si vous choisissez Afficher le code externe.
Dans cet exemple, de gauche à droite, nous voyons ces informations pour le code managé :
- Le thread principal (côté gauche) s’est arrêté sur
Thread.Start
, où le point d’arrêt est identifié par l’icône de marqueur de thread.
- Deux threads sont entrés dans
ServerClass.InstanceMethod
, dont l'un est le thread actuel (flèche jaune), tandis que l'autre thread s'est arrêté dansThread.Sleep
. - Un nouveau thread (à droite) démarre également mais est arrêté sur
ThreadHelper.ThreadStart
.
- Le thread actuel (flèche jaune) est entré en
Pour afficher les threads dans une vue en liste, sélectionnez Déboguer>Windows>Threads.
Dans cette vue, vous pouvez facilement voir que le thread 20272 est le thread principal et se trouve actuellement dans du code externe, en particulier System.Console.dll.
Remarque
Pour plus d’informations sur l’utilisation de la fenêtre Threads, consultez Procédure pas à pas : déboguer une application multithread.
Cliquez avec le bouton droit sur les entrées dans la fenêtre Piles parallèles ou Threads pour afficher les options disponibles dans le menu contextuel.
Vous pouvez effectuer différentes actions à partir de ces menus contextuels. Pour ce tutoriel, vous allez explorer plus de détails dans la fenêtre Parallel Watch (sections suivantes).
Définir une surveillance sur une variable
Ouvrez la fenêtre Parallel Watch en sélectionnant Debug>Windows>Espion parallèle>Espion parallèle 1.
Sélectionnez la cellule dans laquelle vous voyez le
<Add Watch>
texte (ou la cellule d’en-tête vide dans la quatrième colonne) et entrezdata
.Les valeurs de la variable de données pour chaque thread apparaissent dans la fenêtre.
Sélectionnez la cellule dans laquelle vous voyez le
<Add Watch>
texte (ou la cellule d’en-tête vide dans la cinquième colonne) et entrezcount
.Les valeurs de la
count
variable pour chaque thread s’affichent dans la fenêtre. Si vous ne voyez pas encore ces informations, essayez d’appuyer sur F11 plusieurs fois pour avancer l’exécution des threads dans le débogueur.Cliquez avec le bouton droit sur l’une des lignes de la fenêtre pour afficher les options disponibles.
Ajouter et supprimer des threads
Vous pouvez marquer des threads pour suivre les threads importants et ignorer les autres threads.
Dans la fenêtre Espion parallèle , maintenez la touche Maj enfoncée et sélectionnez plusieurs lignes.
Cliquez avec le bouton droit et sélectionnez Indicateur.
Tous les threads sélectionnés sont marqués. À présent, vous pouvez filtrer pour afficher uniquement les threads avec indicateur.
Dans la fenêtre Surveillance parallèle, sélectionnez le bouton Afficher uniquement les threads avec indicateur
.
Seuls les threads avec indicateur apparaissent dans la liste.
Conseil / Astuce
Une fois que vous avez marqué certains threads, vous pouvez cliquer avec le bouton droit sur une ligne de code dans l’éditeur de code et choisir Exécuter des threads avec indicateur sur curseur. Veillez à choisir du code que tous les threads marqués d’un indicateur atteindront. Visual Studio suspend les threads sur la ligne de code sélectionnée, ce qui facilite le contrôle de l’ordre d’exécution en gelant et en dégelant les threads.
Sélectionnez à nouveau le bouton Afficher uniquement les threads avec indicateur pour revenir au mode Afficher tous les threads .
Pour supprimer l’indicateur d’un ou de plusieurs threads, cliquez avec le bouton droit sur le ou les threads concernés dans la fenêtre Espion parallèle, puis sélectionnez Supprimer l’indicateur.
Figer et dégeler l’exécution des threads
Conseil / Astuce
Vous pouvez figer et dégeler (suspendre et reprendre) des threads pour contrôler l’ordre dans lequel les threads effectuent le travail. Cela peut vous aider à résoudre les problèmes de concurrence tels que les conditions de course et les blocages.
Dans la fenêtre Surveillance parallèle, sélectionnez toutes les lignes, cliquez avec le bouton droit et sélectionnez Geler.
Dans la deuxième colonne, une icône de pause s’affiche pour chaque ligne. L’icône de pause indique que le thread est figé.
Désélectionnez toutes les autres lignes en sélectionnant une seule ligne.
Cliquez avec le bouton droit sur une ligne, puis sélectionnez Thaw.
L’icône de pause disparaît sur cette ligne, ce qui indique que le thread n’est plus figé.
Basculez vers l’éditeur de code et appuyez sur F11. Seul le thread libéré s’exécute.
L’application peut également instancier de nouveaux threads. Ceux-ci ne sont ni marqués d’un indicateur, ni gelés.
Suivi d’un seul thread avec des points d’arrêt conditionnels
Il est parfois utile de suivre l’exécution d’un seul thread dans le débogueur. Une façon de le faire consiste à geler les threads qui ne vous intéressent pas. Dans certains scénarios, vous devrez peut-être suivre un thread unique sans figer d’autres threads, par exemple pour reproduire un bogue particulier. Pour suivre un thread sans figer d’autres threads, vous devez éviter d'intervenir dans le code, excepté sur le thread qui vous intéresse. Vous pouvez effectuer cette tâche en définissant un point d’arrêt conditionnel.
Vous pouvez définir des points d’arrêt dans différentes conditions, comme le nom du thread ou l’ID de thread. Il peut être utile de spécifier la condition sur des données dont vous savez qu’elles sont propres à chaque thread. Cette approche est courante lors du débogage lorsque vous êtes plus intéressé par une valeur de données particulière que dans n’importe quel thread particulier.
Cliquez avec le bouton droit sur le point d’arrêt que vous avez créé précédemment et sélectionnez Conditions.
Dans la fenêtre Paramètres de point d'arrêt, entrez
data == 5
pour l’expression conditionnelle.Conseil / Astuce
Si vous êtes plus intéressé par un thread spécifique, utilisez un nom de thread ou un ID de thread pour la condition. Pour ce faire, dans la fenêtre Paramètres du point d'arrêt, sélectionnez Filtrer au lieu de Expression conditionnelle, puis suivez les instructions relatives au filtre. Vous pouvez nommer vos threads dans le code de votre application, à mesure que les ID de threads changent lorsque vous redémarrez le débogueur.
Fermez la fenêtre Paramètres du point d’arrêt .
Sélectionnez le bouton Redémarrer
pour redémarrer votre session de débogage.
Vous allez entrer dans le code sur le thread à l’endroit où la valeur de la variable data est 5. Dans la fenêtre Parallel Watch, cherchez la flèche jaune qui indique le contexte de débogage actuel.
À présent, vous pouvez parcourir le code (F10) et passer au code (F11) et suivre l’exécution du thread unique.
Tant que la condition de point d’arrêt est unique pour le thread et que le débogueur n’atteint aucun autre point d’arrêt sur d’autres threads (vous devrez peut-être les désactiver), vous pouvez parcourir le code et passer au code sans basculer vers d’autres threads.
Remarque
Tous les threads s’exécutent lorsque vous faites avancer le débogueur. Toutefois, celui-ci n’entre dans le code sur d’autres threads que si l’un d’entre eux atteint un point d’arrêt.