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/21 17:24] – Ajout de "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===== | ||
- | ====Sans valeur de retour==== | + | [[https:// |
+ | ====Sans aideur==== | ||
+ | ===Sans valeur de retour=== | ||
<code csharp> | <code csharp> | ||
public static void readControlText(Control varControl) { | public static void readControlText(Control varControl) { | ||
Ligne 15: | Ligne 17: | ||
</ | </ | ||
- | ====Avec valeur de retour==== | + | ===Avec valeur de retour=== |
<code csharp> | <code csharp> | ||
public static string readControlText(Control varControl) { | public static string readControlText(Control varControl) { | ||
Ligne 29: | Ligne 31: | ||
} | } | ||
</ | </ | ||
+ | |||
+ | ====Avec aideur==== | ||
+ | ===Sans valeur de retour=== | ||
+ | <code csharp> | ||
+ | /// < | ||
+ | /// Aideur pour appeler une action soit directement, | ||
+ | /// </ | ||
+ | /// <param name=" | ||
+ | /// <param name=" | ||
+ | public static void AutoInvokeAction(Control control, Action action) | ||
+ | { | ||
+ | if (control.InvokeRequired) | ||
+ | { | ||
+ | control.Invoke((Action)delegate { action(); }); | ||
+ | } | ||
+ | else | ||
+ | { | ||
+ | action(); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | AutoInvokeAction(wiz, | ||
+ | </ | ||
+ | <code csharp> | ||
+ | /// < | ||
+ | /// Aideur pour appeler une fonction soit directement, | ||
+ | /// </ | ||
+ | /// < | ||
+ | /// <param name=" | ||
+ | /// <param name=" | ||
+ | /// < | ||
+ | public static T AutoInvokeFunc< | ||
+ | { | ||
+ | if (control.InvokeRequired) | ||
+ | { | ||
+ | return (T)control.Invoke(new Func< | ||
+ | } | ||
+ | else | ||
+ | { | ||
+ | return function(); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | return AutoInvokeFunc(control, | ||
+ | </ | ||
+ | |||
+ | =====Création des threads===== | ||
+ | |||
+ | ====Thread classique==== | ||
+ | <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 avec lambda expression==== | ||
+ | [[https:// | ||
+ | <code csharp> | ||
+ | Thread t = new Thread(() => | ||
+ | { | ||
+ | // Action à faire | ||
+ | }); | ||
+ | t.Start(); | ||
+ | </ | ||
+ | |||
+ | ou directement : | ||
+ | <code csharp> | ||
+ | new Thread(() => | ||
+ | { | ||
+ | // Action à faire | ||
+ | }).Start(); | ||
+ | </ | ||
+ | |||
+ | ====Thread se répétant==== | ||
+ | <code csharp> | ||
+ | date = new System.Threading.Timer( | ||
+ | (state) => | ||
+ | { | ||
+ | // Faire ce qu'on veut. | ||
+ | }, | ||
+ | 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.1542817459.txt.gz · Dernière modification : 2018/11/21 17:24 de root