FAQ C#Consultez toutes les FAQ

Nombre d'auteurs : 41, nombre de questions : 272, dernière mise à jour : 16 août 2017  Ajouter une question

 

Cette FAQ a été réalisée pour répondre aux questions les plus fréquemment posées concernant C# sur le forum Développement DotNET

Je tiens à souligner qu'elle ne garantit en aucun cas que les informations qu'elle contient sont correctes ; les auteurs font le maximum, mais l'erreur est humaine. Si vous trouvez une erreur, ou que vous souhaitez devenir rédacteur, lisez ceci .

Sur ce, je vous souhaite une bonne lecture.

Commentez cette FAQ : Commentez


Sommaire.NET FrameworkThreads (8)
précédent sommaire suivant
 

Pour créer un thread, il faut utiliser la classe System.Threading.Thread.

Considérons que l'on dispose d'une Form.
Nous avons besoin de déclarer notre objet thread à l'intérieur de la Form.

Code c# : Sélectionner tout
1
2
3
4
5
6
7
8
using System.Threading; 
  
public class Threads : System.Windows.Forms.Form 
{ 
    // ... 
  
    private Thread _threadCalculs1; 
}
La fonction exécutée par le thread a une signature imposée par le .NET Framework. Il s'agit du délégué System.Threading.ThreadStart.
C'est une fonction qui ne prend aucun paramètre et ne possède pas de valeur de retour.
On peut la déclarer ainsi dans notre Form.

Code c# : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
using System.Threading; 
  
public class Threads : System.Windows.Forms.Form 
{ 
  
    // ... 
  
    private void ThrFunc1() 
    { 
        // Traitement effectué par le thread. Calculs est une fonction quelconque de notre Form 
        try 
        { 
            Calculs(1000); 
        } 
        catch (Exception ex) 
        { 
            Debug.WriteLine(ex.ToString()); 
        } 
    } 
}
Pour démarrer le thread, on utilise la fonction Start de la classe Thread.

Code c# : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
using System.Threading; 
  
public class Threads : System.Windows.Forms.Form 
{ 
  
    // ... 
  
    private void StartThread() 
    { 
        // ThrFunc est la fonction exécutée par le thread. 
        _threadCalculs1 = new Thread(new ThreadStart(ThrFunc1)); 
        // Il est parfois pratique de nommer les threads surtout si on en créé plusieurs. 
        _threadCalculs1.Name = "Thread1"; 
        // Démarrage du thread. 
        _threadCalculs1.Start(); 
    } 
}

Mis à jour le 2 novembre 2004 abelman

Le délégué System.Threading.ThreadStart utilisé pour les fonctions de thread ne prend pas de paramètres.
Pour passer des paramètres à un thread, il vous faut créer une classe pour contenir les paramètres et la méthode du thread.

Code c# : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
    public class ThreadParametre 
    { 
        private string _text; 
        private int _entier; 
  
        // Constructeur 
        public ThreadParametre(string texte, int entier) 
        { 
            _text = texte; 
            _entier = entier; 
        } 
  
        // Exécution de la méthode du thread 
        public void ExecuteThread() 
        { 
            for (int i = 0; i < _entier; i++) 
            { 
                Console.WriteLine("Index : " + i); 
                Console.WriteLine("Message : " + _text); 
            } 
        } 
    } 
  
    public class Exemple 
    { 
        // Point d'entrée de l'application 
        public static void Main() 
        { 
            ThreadParametre ExempleThread = new ThreadParametre("Message de test", 5); 
            Thread t = new Thread(new ThreadStart(ExempleThread.ExecuteThread)); 
            t.Start(); 
        } 
    }

Mis à jour le 2 novembre 2004 abelman Thomas Lebrun

Le meilleur moyen d'arrêter un thread est de laisser sa fonction se terminer.
Si une fonction de thread s'exécute en continu dans une boucle, il est nécessaire d'écrire un code qui prévoit une condition pour sortir de la boucle. Cette condition doit pouvoir être modifiée par d'autres threads.

Reprenons l'exemple de notre Form (voir Comment créer et lancer un thread ?).
Pour signaler au thread que nous souhaitons qu'il s'arrête, nous allons utiliser un objet de la classe System.Threading.AutoResetEvent.
Dans la boucle de la fonction du thread, nous faisons attendre le thread pendant un court laps de temps. Si l'objet AutoResetEvent passe à l'état signalé, alors on sort du thread.

Code c# : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
using System.Threading; 
  
public class Thread : System.Windows.Forms.Form 
{ 
  
    // ... 
  
    // Evènement de signal de fin de thread 
    private AutoResetEvent _endThreadCalculsEvent = new AutoResetEvent(false); 
  
    // Pour arrêter le thread 
    private void Button2_Click(Object sender, System.EventArgs e) 
    { 
        // L'evenement passe à l'état signalé 
        _endThreadCalculsEvent.Set(); 
        // On attend la fin du thread. 
        _threadCalculs1.Join(); 
    } 
  
    // Fonction du thread 
    private void ThrFunc1() 
    { 
        try 
        { 
            Calculs(1000); 
        } 
        catch (Exception ex) 
        { 
            Debug.WriteLine(ex.ToString()); 
        } 
  
    } 
  
    private void Calculs(int tempor) 
    { 
        // Si l'évenement est à l'état signalé, WaitOne renvoie true et la boucle se termine. 
        while (!_endThreadCalculsEvent.WaitOne(tempo, false)) 
        { 
            // C'est ici ou notre thread fait son travail 
            // ... 
        } 
    } 
}
Il existe un moyen plus radical d'arrêter un thread, c'est l'utilisation de la fonction Thread.Abort.
Lorsque vous appelez Abort, le Runtime lève une exception ThreadAbortException que le thread peut alors intercepter.
C'est aussi pourquoi il est déconseillé d'utiliser Abort car on ne peut prévoir où en est le thread dans son traitement. Lever une exception peut interrompre le thread alors qu'il est dans une partie du code qu'il doit terminer avant de sortir.
Un des exemples où on peut utiliser Abort sans risque : la fonction du thread est bloquée infiniment sur un appel (une attente de connexion socket par exemple)

Code c# : Sélectionner tout
1
2
3
4
5
6
// Forcer la fin du thread 
private void AbortThread() 
{ 
    _threadCalculs1.Abort();  // On demande au runtime d'arrêter le Thread 
    _threadCalculs1.Join();   //  On attend la fin du thread. 
}
Un thread terminé ne peut plus être relancé. Il faut instancier un nouvel objet Thread pour chaque démarrage de thread.

Mis à jour le 2 novembre 2004 abelman

Tout d'abord pensez à la clause using System.Threading. Pour changer le nom du thread courant, ajouter la ligne de code suivante :

Code c# : Sélectionner tout
Thread.CurrentThread.Name = "MainThread";
Ici on donne le nom « MainThread » au thread courrant. Si vous devez réaliser cela pour le thread principal, alors il faut ajouter cette ligne avant le Application.Run.

Mis à jour le 22 août 2006 loic38760

La ligne suivante permet de mettre un terme à la tranche de temps que le Thread a pour utiliser le processeur :

Code c# : Sélectionner tout
Thread.Sleep(0);

Mis à jour le 2 janvier 2007 Jérôme Lambert

La classe Interlocked fournit des méthodes permettant d'effectuer des opérations mathématiques de manière atomique lorsque plusieurs threads se partagent des variables.

Code c# : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
int SharedValue = 100; 
  
// Addition 
Interlocked.Add(ref SharedValue, 10); 
  
// Soustraction 
Interlocked.Add(ref SharedValue, -10); 
  
// Incrémentation 
Interlocked.Increment(ref SharedValue); 
  
// Décrémentation 
Interlocked.Decrement(ref SharedValue); 
  
// Copie 
int SharedValue2 = 50; 
Interlocked.Exchange(ref SharedValue, SharedValue2); 
  
// Comparaison et Copie 
// Comparaison entre paramètres 1 et 3 
// si égalité, SharedValue = 100 
Interlocked.CompareExchange(ref SharedValue, 100, 50); 
  
// Lecture 
long SharedValueLong = 30; 
long ValueSafe = Interlocked.Read(ref SharedValueLong);
À noter que les membres de cette classe ne lèvent pas d'exception.

Mis à jour le 2 janvier 2007 Jérôme Lambert

La classe Monitor permet à un thread de mettre un verrou sur des objets. Ainsi, aucun autre thread ne pourra mettre son verrou sur les objets déjà verrouillés.

Code c# : Sélectionner tout
1
2
3
4
5
6
7
// Met un verrou sur this 
Monitor.Enter(this); 
  
// ... 
  
// Retire le verrou sur this 
Monitor.Exit(this);

Mis à jour le 2 janvier 2007 Jérôme Lambert

La classe Mutex permet à un thread d'avoir un accès exclusif à une portion de code, les autres threads étant bloqués s'ils désirent accéder à cette portion de code.

Code c# : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
static class MutexExample 
{ 
    // Déclaration du Mutex 
    static Mutex monMutex; 
  
    static void Main() 
    { 
        // Initialisation du Mutex 
        monMutex = new Mutex(); 
  
        // Création de 2 threads 
        Thread T1 = new Thread(new ThreadStart(FonctionA)); 
        Thread T2 = new Thread(new ThreadStart(FonctionB)); 
  
        // Démarrage des threads 
        T1.Start(); 
        T2.Start(); 
  
        // Attendre la fin des threads 
        T1.Join(); 
        T2.Join(); 
  
        Console.ReadLine(); 
    } 
  
    /// <summary> 
    /// Méthode du thread A 
    /// </summary> 
    static void FonctionA() 
    { 
        for (int i = 0; i < 3; i++) 
        { 
            Console.WriteLine("Thread A > J'ai faim"); 
            Manger(); 
  
            Console.WriteLine("Thread A > J'en peux plus..."); 
            Thread.Sleep(100); 
        } 
  
        Console.WriteLine("Thread A > Oh non, déjà fini :("); 
    } 
  
    /// <summary> 
    /// Méthode du thread B 
    /// </summary> 
    static void FonctionB() 
    { 
        for (int i = 0; i < 3; i++) 
        { 
            Console.WriteLine("Thread B > J'ai faim"); 
            Manger(); 
  
            Console.WriteLine("Thread B > J'en peux plus..."); 
            Thread.Sleep(200); 
        } 
  
        Console.WriteLine("Thread B > Oh non, déjà fini :("); 
    } 
  
    /// <summary> 
    /// Méthode représentant la section critique 
    /// </summary> 
    static void Manger() 
    { 
        monMutex.WaitOne(); 
  
        Thread.Sleep(50); 
  
        monMutex.ReleaseMutex(); 
    } 
}
Attention toutefois, depuis la version 2 du Framework, une exception AbandonedMutexException est levée lorsqu'un thread désire acquérir un Mutex qui appartenait à un thread qui s'est terminé sans le libérer.

Mis à jour le 2 janvier 2007 Jérôme Lambert

Proposer une nouvelle réponse sur la FAQ

Ce n'est pas l'endroit pour poser des questions, allez plutôt sur le forum de la rubrique pour ça


Réponse à la question

Liens sous la question
précédent sommaire suivant
 

Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright © 2017 Developpez Developpez LLC. Tous droits réservés Developpez LLC. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents et images sans l'autorisation expresse de Developpez LLC. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.

 
Responsable bénévole de la rubrique Microsoft DotNET : Hinault Romaric -