Pour comprendre le filetage dans VB.NET, il est utile de comprendre certains des concepts de base. Tout d'abord, le filetage est quelque chose qui se produit parce que le système d'exploitation le prend en charge. Microsoft Windows est un système d'exploitation multitâche préventif. Une partie de Windows appelée le planificateur de tâches répartit le temps processeur sur tous les programmes en cours d'exécution. Ces petits morceaux de temps processeur sont appelés tranches de temps. Les programmes ne sont pas responsables du temps processeur dont ils disposent, le planificateur de tâches l'est. Parce que ces tranches de temps sont si petites, vous avez l'illusion que l'ordinateur fait plusieurs choses à la fois.
Définition du fil
Un thread est un flux de contrôle séquentiel unique.
Quelques qualificatifs:
- Un thread est un "chemin d'exécution" à travers ce corps de code.
- Les threads partagent la mémoire et doivent donc coopérer pour produire le résultat correct.
- Un thread a des données spécifiques au thread telles que des registres, un pointeur de pile et un compteur de programme.
- Un processus est un corps de code unique qui peut avoir plusieurs threads, mais il en a au moins un et il a un seul contexte (espace d'adressage).
Ce sont des trucs au niveau de l'assemblage, mais c'est ce que vous entrez lorsque vous commencez à penser aux threads.
Multithreading vs. Multiprocessing
Multithreading n'est pas la même chose que le traitement parallèle multicœur, mais le multithreading et le multitraitement fonctionnent ensemble. La plupart des PC ont aujourd'hui des processeurs qui ont au moins deux cœurs, et les machines domestiques ordinaires ont parfois jusqu'à huit cœurs. Chaque cœur est un processeur séparé, capable d'exécuter des programmes par lui-même. Vous obtenez une amélioration des performances lorsque le système d'exploitation attribue un processus différent à différents cœurs. L'utilisation de plusieurs threads et de plusieurs processeurs pour des performances encore plus élevées est appelée parallélisme au niveau des threads.
Beaucoup de ce qui peut être fait dépend de ce que le système d'exploitation et le matériel du processeur peuvent faire, pas toujours ce que vous pouvez faire dans votre programme, et vous ne devez pas vous attendre à pouvoir utiliser plusieurs threads sur tout. En fait, vous ne trouverez peut-être pas beaucoup de problèmes qui bénéficient de plusieurs threads. Donc, n'implémentez pas le multithreading juste parce qu'il est là. Vous pouvez facilement réduire les performances de votre programme s'il n'est pas un bon candidat pour le multithreading. Tout comme les exemples, les codecs vidéo peuvent être les pires programmes à multithread car les données sont intrinsèquement en série. Les programmes serveur qui gèrent les pages Web sont peut-être parmi les meilleurs car les différents clients sont intrinsèquement indépendants.
Pratiquer la sécurité des fils
Le code multithread nécessite souvent une coordination complexe des threads. Les bogues subtils et difficiles à trouver sont courants car différents threads doivent souvent partager les mêmes données afin que les données puissent être modifiées par un thread lorsqu'un autre ne s'y attend pas. Le terme général pour ce problème est «condition de concurrence». En d'autres termes, les deux threads peuvent entrer dans une "course" pour mettre à jour les mêmes données et le résultat peut être différent selon le thread "gagnant". À titre d'exemple trivial, supposons que vous codiez une boucle:
Si le compteur de boucle «I» manque de façon inattendue le nombre 7 et passe de 6 à 8 - mais seulement une partie du temps - cela aurait des effets désastreux sur tout ce que fait la boucle. La prévention de tels problèmes s'appelle la sécurité des threads. Si le programme a besoin du résultat d'une opération dans une opération ultérieure, il peut être impossible de coder des processus ou des threads parallèles pour le faire.
Opérations de base de multithreading
Il est temps de pousser ce discours de précaution à l'arrière-plan et d'écrire du code multithreading. Cet article utilise une application console pour plus de simplicité en ce moment. Si vous souhaitez suivre, démarrez Visual Studio avec un nouveau projet d'application console.
L'espace de noms principal utilisé par le multithreading est le système. L'espace de noms Threading et la classe Thread créent, démarrent et arrêtent de nouveaux threads. Dans l'exemple ci-dessous, notez que TestMultiThreading est un délégué. Autrement dit, vous devez utiliser le nom d'une méthode que la méthode Thread peut appeler.
Dans cette application, nous aurions pu exécuter le deuxième Sub en l'appelant simplement:
Cela aurait exécuté l'ensemble de l'application en mode série. Le premier exemple de code ci-dessus, cependant, démarre le sous-programme TestMultiThreading et continue ensuite.
Un exemple d'algorithme récursif
Voici une application multithread impliquant le calcul des permutations d'un tableau à l'aide d'un algorithme récursif. Tout le code n'est pas affiché ici. Le tableau de caractères permuté est simplement «1», «2», «3», «4» et «5». Voici la partie pertinente du code.
Notez qu'il existe deux façons d'appeler le sub Permute (tous deux commentés dans le code ci-dessus). L'un lance un fil et l'autre l'appelle directement. Si vous l'appelez directement, vous obtenez:
Cependant, si vous lancez un thread et démarrez le sous-permutation à la place, vous obtenez:
Cela montre clairement qu'au moins une permutation est générée, puis le sous-marin principal avance et se termine, affichant "Finished Main", tandis que le reste des permutations sont générées. Étant donné que l'affichage provient d'un deuxième sous-appel appelé par le sub Permute, vous savez que cela fait également partie du nouveau thread. Cela illustre le concept selon lequel un thread est "un chemin d'exécution" comme mentionné précédemment.
Exemple de condition de course
La première partie de cet article mentionne une condition de concurrence. Voici un exemple qui le montre directement:
La fenêtre Immédiat a montré ce résultat dans un essai. D'autres essais étaient différents. C'est l'essence même d'une condition de concurrence.