English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Multithreading C#

Thread défini comme un chemin d'exécution du programme. Chaque thread définit un flux de contrôle unique. Si votre application implique des opérations complexes et chronophages, il est souvent bénéfique de configurer des chemins d'exécution de threads distincts, chaque thread exécutant une tâche spécifique.

Un thread estProcessus légerUn exemple commun d'utilisation des threads est l'implémentation de la programmation par lot dans les systèmes d'exploitation modernes. L'utilisation des threads économise les cycles de CPU gaspillés tout en améliorant l'efficacité de l'application.

Jusqu'à présent, le programme que nous avons écrit est un processus unique qui s'exécute en tant que exemple de programme mono-threadé de l'application. Cependant, une application ainsi conçue ne peut exécuter qu'une tâche à la fois. Pour exécuter plusieurs tâches en même temps, elle peut être divisée en plus petits threads.

Vie du thread

La vie du thread commence lorsque l'objet de la classe System.Threading.Thread est créé, et se termine lorsque le thread est terminé ou a terminé son exécution.

Voici une liste des différents états de la vie du thread :

  • État non démarré: État lorsque l'exemple de thread est créé mais que la méthode Start n'a pas été appelée.

  • État prêt: État lorsque le thread est prêt à s'exécuter et attend un cycle CPU.

  • État non exécutable: Les threads ne peuvent pas être exécutés dans les seguintes situations :

    • La méthode Sleep a déjà été appelée

    • La méthode Wait a déjà été appelée

    • à travers I/Blocage de l'opérateur O

  • État mort: État lorsque le thread a terminé son exécution ou a été interrompu.

Thread principal

Dans C#,System.Threading.Thread La classe est utilisée pour le travail des threads. Elle permet de créer et d'accéder à un seul thread dans une application multithreadée. Le premier thread exécuté dans le processus est appeléThread principal.

Lorsque le programme C# commence à s'exécuter, le thread principal est créé automatiquement. Utilisez Thread Les threads créés par la classe sont appelés par les sous-threads de la thread principale. Vous pouvez utiliser les méthodes de la classe Thread CurrentThread Accès aux propriétés du thread.

Le programme suivant demonstrates the execution of the main thread:

using System;
using System.Threading;
namespace MultithreadingApplication
{
    class MainThreadProgram
    {
        static void Main(string[] args)
        {
            Thread th = Thread.CurrentThread;
            th.Name = "MainThread";
            Console.WriteLine("This is {0}", th.Name);
            Console.ReadKey();
        }
    }
}

Lorsque le code suivant est compilé et exécuté, il produit le résultat suivant :

This is MainThread

Propriétés et méthodes couramment utilisées par la classe Thread

Le tableau suivant liste Thread Des méthodes couramment utilisées d'une classe Propriétés:

PropriétésDescription
CurrentContextObtenir le contexte courant dans lequel le thread s'exécute.
CurrentCultureObtenir ou définir la régionalité courante du thread.
CurrentPrincipalObtenir ou définir le responsable courant du thread (pour la sécurité basée sur les rôles).
CurrentThreadObtenir le thread en cours d'exécution.
CurrentUICultureObtenir ou définir la régionalité courante utilisée par le gestionnaire de ressources pour trouver des ressources spécifiques à la régionalité au moment de l'exécution.
ExecutionContextObtenir un objet ExecutionContext, qui contient diverses informations sur le contexte du thread courant.
IsAliveObtenez une valeur qui indique l'état d'exécution du thread actuel.
IsBackgroundObtenez ou définissez une valeur qui indique si un thread est un thread d'arrière-plan.
IsThreadPoolThreadObtenez une valeur qui indique si le thread appartient au pool de threads gérés.
ManagedThreadIdObtenez l'identifiant unique du thread géré.
NameObtenez ou définissez le nom du thread.
PriorityObtenez ou définissez une valeur qui indique la priorité de planification du thread.
ThreadStateObtenez une valeur qui contient l'état actuel du thread.

Le tableau suivant liste Thread Des méthodes couramment utilisées d'une classe Méthode:

NuméroNom de la méthode & Description
1public void Abort()
Lancez une exception ThreadAbortException sur le thread appelant cette méthode pour commencer le processus de terminaison de ce thread. L'appel à cette méthode terminera généralement le thread.
2public static LocalDataStoreSlot AllocateDataSlot()
Allouez un slot de données non nommé sur tous les threads. Pour une meilleure performance, utilisez des champs marqués avec l'attribut ThreadStaticAttribute.
3public static LocalDataStoreSlot AllocateNamedDataSlot( string name)
Allouez un slot de données nommé sur tous les threads. Pour une meilleure performance, utilisez des champs marqués avec l'attribut ThreadStaticAttribute.
4public static void BeginCriticalRegion()
Notifiez le hôte que l'exécution va entrer dans une zone de code où l'interruption du thread ou l'exception non traitée pourrait nuire à d'autres tâches dans le domaine de l'application.
5public static void BeginThreadAffinity()
Notifiez le hôte que le code géré va exécuter une instruction dépendante de l'identifiant du thread de l'exploitation système actuelle.
6public static void EndCriticalRegion()
Notifiez le hôte que l'exécution va entrer dans une zone de code où l'interruption du thread ou l'exception non traitée peut affecter uniquement la tâche actuelle.
7public static void EndThreadAffinity()
Notifiez le hôte que le code géré a exécuté une instruction dépendante de l'identifiant du thread de l'exploitation système actuelle.
8public static void FreeNamedDataSlot(string name)
为进程中的所有线程消除名称与槽之间的关联。为了获得更好的性能,请改用以 ThreadStaticAttribute 属性标记的字段。
9public static Object GetData( LocalDataStoreSlot slot )
在当前线程的当前域中从当前线程上指定的槽中检索值。为了获得更好的性能,请改用以 ThreadStaticAttribute 属性标记的字段。
10public static AppDomain GetDomain()
返回当前线程正在其中运行的当前域。
11public static AppDomain GetDomainID()
返回唯一的应用程序域标识符。
12public static LocalDataStoreSlot GetNamedDataSlot( string name )
查找已命名的数据槽。为了获得更好的性能,请改用以 ThreadStaticAttribute 属性标记的字段。
13public void Interrupt()
中断处于 WaitSleepJoin 线程状态的线程。
14public void Join()
在继续执行标准的 COM 和 SendMessage 消息泵处理期间,阻塞调用线程,直到某个线程终止为止。此方法有不同的重载形式。
15public static void MemoryBarrier()
按如下方式同步内存存取:执行当前线程的处理器在对指令重新排序时,不能采用先执行 MemoryBarrier 调用之后的内存存取,再执行 MemoryBarrier 调用之前的内存存取的方式。
16public static void ResetAbort()
取消为当前线程请求的 Abort。
17public static void SetData( LocalDataStoreSlot slot, Object data )
在当前正在运行的线程上为此线程的当前域在指定槽中设置数据。为了获得更好的性能,请改用以 ThreadStaticAttribute 属性标记的字段。
18public void Start()
启动一个线程。
19public static void Sleep( int millisecondsTimeout )
faire arrêter temporairement le thread pendant un certain temps.
20public static void SpinWait( int iterations )
cause le thread à attendre le temps défini par le paramètre iterations.
21public static byte VolatileRead( ref byte address )
public static double VolatileRead( ref double address )
public static int VolatileRead( ref int address )
public static Object VolatileRead( ref Object address )

lire la valeur du champ. Quelle que soit le nombre de processeurs ou l'état des caches de processeurs, la valeur est écrite par n'importe quel processeur de l'ordinateur avec la valeur la plus récente. Cette méthode a différentes formes de surcharge. Ici, seules quelques formes sont données.
22public static void VolatileWrite( ref byte address, byte value )
public static void VolatileWrite( ref double address, double value )
public static void VolatileWrite( ref int address, int value )
public static void VolatileWrite( ref Object address, Object value )

Écrire immédiatement une valeur dans un champ pour rendre cette valeur visible pour tous les processeurs de l'ordinateur. Cette méthode a différentes formes de surcharge. Ici, seules quelques formes sont données.
23public static bool Yield()
cause l'appel d'un autre thread prêt à s'exécuter sur le processeur actuel. Le système d'exploitation choisit le thread à exécuter.

création de thread

Les threads sont créés en étendant la classe Thread. L'étendue de la classe Thread appelle Start() une méthode pour commencer l'exécution du thread secondaire.

Le programme suivant illustre ce concept :

using System;
using System.Threading;
namespace MultithreadingApplication
{
    class ThreadCreationProgram
    {
        public static void CallToChildThread()
        {
            Console.WriteLine("Child thread starts");
        }
        
        static void Main(string[] args)
        {
            ThreadStart childref = new ThreadStart(CallToChildThread);
            Console.WriteLine("In Main: Creating the Child thread");
            Thread childThread = new Thread(childref);
            childThread.Start();
            Console.ReadKey();
        }
    }
}

Lorsque le code suivant est compilé et exécuté, il produit le résultat suivant :

In Main: Creating the Child thread
Child thread starts

gestion des threads

La classe Thread fournit diverses méthodes de gestion des threads.

L'exemple suivant montre sleep() l'utilisation de la méthode, utilisée pour arrêter temporairement un thread à un moment spécifique.

using System;
using System.Threading;
namespace MultithreadingApplication
{
    class ThreadCreationProgram
    {
        public static void CallToChildThread()
        {
            Console.WriteLine("Child thread starts");
            // arrêt du thread 5000 millisecondes
            int sleepfor = 5000; 
            Console.WriteLine("Filthread arrêté pendant {0} secondes", 
                              sleepfor / 1000);
            Thread.Sleep(sleepfor);
            Console.WriteLine("Filthread reprend");
        }
        
        static void Main(string[] args)
        {
            ThreadStart childref = new ThreadStart(CallToChildThread);
            Console.WriteLine("In Main: Creating the Child thread");
            Thread childThread = new Thread(childref);
            childThread.Start();
            Console.ReadKey();
        }
    }
}

Lorsque le code suivant est compilé et exécuté, il produit le résultat suivant :

In Main: Creating the Child thread
Child thread starts
Child Thread Paused for 5 seconds
Child thread resumes

销毁线程

Abort() 方法用于销毁线程。

通过抛出 threadabortexception 在运行时中止线程。这个异常不能被捕获,如果有 finally 块,控制会被送至 finally 块。

下面的程序说明了这点:

using System;
using System.Threading;
namespace MultithreadingApplication
{
    class ThreadCreationProgram
    {
        public static void CallToChildThread()
        {
            try
            {
                Console.WriteLine("Child thread starts");
                // 计数到 10
                for(int counter = 0; counter <= 10; counter++)
                {
                    Thread.Sleep(500);
                    Console.WriteLine(counter);
                }
                Console.WriteLine("Child Thread Completed");
            }
            catch(ThreadAbortException e)
            {
                Console.WriteLine("Thread Abort Exception");
            }
            finally
            {
                Console.WriteLine("Couldn't catch the Thread Exception");
            }
        }
        
        static void Main(string[] args)
        {
            ThreadStart childref = new ThreadStart(CallToChildThread);
            Console.WriteLine("In Main: Creating the Child thread");
            Thread childThread = new Thread(childref);
            childThread.Start();
            // 停止主线程一段时间
            Thread.Sleep(2000);
            // 现在中止子线程
            Console.WriteLine("In Main: Aborting the Child thread");
            childThread.Abort();
            Console.ReadKey();
        }
    }
}

Lorsque le code suivant est compilé et exécuté, il produit le résultat suivant :

In Main: Creating the Child thread
Child thread starts
0
1
2
In Main: Aborting the Child thread
Thread Abort Exception
Couldn't catch the Thread Exception