lang:csharp:thread
Différences
Ci-dessous, les différences entre deux révisions de la page.
| Les deux révisions précédentesRévision précédenteProchaine révision | Révision précédente | ||
| lang:csharp:thread [2018/11/29 12:33] – Ajout des aideurs pour "Invoke" root | lang:csharp:thread [2020/05/11 00:51] (Version actuelle) – Fix alignement des images root | ||
|---|---|---|---|
| Ligne 3: | Ligne 3: | ||
| =====Blocage inter-threads===== | =====Blocage inter-threads===== | ||
| - | [[https:// | + | [[https:// |
| ====Sans aideur==== | ====Sans aideur==== | ||
| ===Sans valeur de retour=== | ===Sans valeur de retour=== | ||
| Ligne 78: | Ligne 78: | ||
| =====Création des threads===== | =====Création des threads===== | ||
| - | ====Thread | + | |
| + | ====Thread | ||
| + | <WRAP center round important 60%> | ||
| + | D'une manière générale, je déconseille l' | ||
| + | |||
| + | {{: | ||
| + | |||
| + | Donc pour que chaque Thread reste bien indépendant, | ||
| + | </ | ||
| + | |||
| + | <code csharp> | ||
| + | public static class Simulation | ||
| + | { | ||
| + | // Pas de risque de race condition, la valeur est modifiée | ||
| + | // par une seule ligne de code extérieure et n'est pas modifiée par Execution(). | ||
| + | public static long finSimul; | ||
| + | |||
| + | public static void Execution() | ||
| + | { | ||
| + | } | ||
| + | } | ||
| + | |||
| + | new Thread(new ThreadStart(Simulation.Execution)).Start(); | ||
| + | </ | ||
| + | |||
| + | ====Thread classique | ||
| [[https:// | [[https:// | ||
| <code csharp> | <code csharp> | ||
| Ligne 105: | Ligne 130: | ||
| this, 0, 1000); // Toutes les 1000 millisecondes. | this, 0, 1000); // Toutes les 1000 millisecondes. | ||
| </ | </ | ||
| + | |||
| + | =====Threads accédant aux composants d'une form===== | ||
| + | Il faut arrêter les threads accédant aux composants d'une Form avant de la détruire. Sinon, des exceptions vont être générées. | ||
| + | |||
| + | La solution la plus simple est d' | ||
| + | |||
| + | Mais si on souhaite un arrêt non brutal des threads, on peut utiliser la classe ci-dessous. | ||
| + | |||
| + | On crée un '' | ||
| + | |||
| + | A la fermeture de la fenêtre, on appelle la méthode '' | ||
| + | |||
| + | <file csharp ManageThread.cs> | ||
| + | public class ManageThread | ||
| + | { | ||
| + | /// < | ||
| + | /// Stockage de tous les threads. | ||
| + | /// </ | ||
| + | private List< | ||
| + | |||
| + | /// < | ||
| + | /// Autorise ou pas les ajout de threads. | ||
| + | /// Quand ManageThread est en train de purger tous les threads (via JoinAllThreads()), | ||
| + | /// on empêche l' | ||
| + | /// </ | ||
| + | private bool allowAdd = true; | ||
| + | |||
| + | /// < | ||
| + | /// On ajoute un thread à la liste. | ||
| + | /// En même temps, on s' | ||
| + | /// </ | ||
| + | /// <param name=" | ||
| + | public bool Add(Thread t) | ||
| + | { | ||
| + | lock (allThreads) | ||
| + | { | ||
| + | for (int i = allThreads.Count - 1; i >= 0; i--) | ||
| + | { | ||
| + | if (!allThreads[i].IsAlive) | ||
| + | { | ||
| + | allThreads.RemoveAt(i); | ||
| + | } | ||
| + | } | ||
| + | if (!allowAdd) | ||
| + | return false; | ||
| + | allThreads.Add(t); | ||
| + | return true; | ||
| + | } | ||
| + | } | ||
| + | |||
| + | /// < | ||
| + | /// On attend que tous les threads restants s' | ||
| + | /// Si une fonction parallèle en ajoute aussi en boucle, on ne quitte jamais la fonction. | ||
| + | /// </ | ||
| + | public void JoinAllThreads() | ||
| + | { | ||
| + | lock (allThreads) | ||
| + | { | ||
| + | allowAdd = false; | ||
| + | } | ||
| + | while (true) | ||
| + | { | ||
| + | Thread t; | ||
| + | lock (allThreads) | ||
| + | { | ||
| + | if (allThreads.Count == 0) | ||
| + | return; | ||
| + | t = allThreads[0]; | ||
| + | } | ||
| + | t.Join(); | ||
| + | lock (allThreads) | ||
| + | { | ||
| + | // Pas RemoveAt(0). | ||
| + | allThreads.Remove(t); | ||
| + | } | ||
| + | } | ||
| + | } | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | Utilisation : | ||
| + | <code csharp> | ||
| + | public partial class Form1 : Form | ||
| + | { | ||
| + | private ManageThread manageThread = new ManageThread(); | ||
| + | | ||
| + | Thread t = new Thread(() => | ||
| + | { | ||
| + | // Travail à faire. | ||
| + | }); | ||
| + | // Si besoin, on peut vérifier si le thread a démarré. | ||
| + | manageThread.Add(t); | ||
| + | | ||
| + | private void Form1_FormClosed(object sender, FormClosedEventArgs e) | ||
| + | { | ||
| + | // Ici, on arrête éventuellement tous les threads ajoutant des threads à manageThread. | ||
| + | manageThread.JoinAllThreads(); | ||
| + | } | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | =====Threads lambda utilisant une variable locale===== | ||
| + | [[https:// | ||
| + | |||
| + | Mauvais : | ||
| + | <code csharp> | ||
| + | for (int i = 0; i < 2; i++) | ||
| + | { | ||
| + | Thread t = new Thread(() => | ||
| + | { | ||
| + | // i vaudra toujours 2 car le thread sera appelé après la boucle. | ||
| + | Console.WriteLine(i); | ||
| + | }); | ||
| + | t.Start(); | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | Bon : | ||
| + | <code csharp> | ||
| + | for (int i = 0; i < 2; i++) | ||
| + | { | ||
| + | // Variable locale. | ||
| + | int j = i; | ||
| + | Thread t = new Thread(() => | ||
| + | { | ||
| + | Console.WriteLine(j); | ||
| + | }); | ||
| + | t.Start(); | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | <code csharp> | ||
| + | Parallel.For(0, | ||
| + | i => | ||
| + | { | ||
| + | Console.WriteLine(i); | ||
| + | } | ||
| + | ); | ||
| + | </ | ||
| + | Il est important de préciser le nombre maxi de threads sinon, si la charge baisse lors de l' | ||
lang/csharp/thread.1543491219.txt.gz · Dernière modification : de root
