Tutoriel C#SE CONNECTER
Tutoriel C#
auteur:php.cn  temps de mise à jour:2022-04-11 14:06:23

Multithreading C#



Thread est défini comme le 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 avantageux de configurer différents chemins d'exécution des threads, chaque thread effectuant un travail spécifique.

Les threads sont des processus légers. Un exemple courant d'utilisation de threads est la mise en œuvre de la programmation parallèle dans les systèmes d'exploitation modernes. L’utilisation de threads permet d’économiser des cycles CPU inutiles tout en augmentant l’efficacité des applications.

Le programme que nous avons écrit jusqu'à présent est un seul thread exécuté comme un processus unique de l'instance en cours d'exécution de l'application. Cependant, cette sous-application ne peut effectuer qu'une seule tâche à la fois. Afin d'effectuer plusieurs tâches simultanément, il peut être divisé en threads plus petits.

Cycle de vie du thread

Le cycle de vie du thread commence lorsqu'un objet de la classe System.Threading.Thread est créé et se termine lorsque le thread est terminé ou termine son exécution.

Les différents états du cycle de vie du thread sont répertoriés ci-dessous :

  • État non démarré  : lorsque l'instance de thread est créée mais que la méthode Start a pas La condition lors de l'appel.

  • État prêt  : La condition dans laquelle un thread est prêt à s'exécuter et attend les cycles du processeur.

  • Statut inopérant : Le fil de discussion est inutilisable dans les situations suivantes :


    • La méthode de veille a été appelée

    • La méthode d'attente a été appelée

    • Bloquée par une opération d'E/S

  • Statut de mort : La condition dans laquelle un thread a terminé son exécution ou a été terminé.

Main Thread

En C#, la classe System.Threading.Thread est utilisée pour le travail des threads. Il permet la création et l'accès à des threads individuels dans des applications multithread. Le premier thread à exécuter dans le processus est appelé thread principal.

Lorsque le programme C# démarre son exécution, le thread principal est automatiquement créé. Les threads créés à l'aide de la classe Thread sont appelés par les threads enfants du thread principal. Vous pouvez accéder aux threads en utilisant la propriété CurrentThread de la classe Thread.

Le programme suivant démontre l'exécution du thread principal :

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 ci-dessus est compilé et exécuté, il produira les résultats suivants :

This is MainThread

Classe de thread communément Attributs et méthodes utilisés

Le tableau suivant répertorie certains attributs couramment utilisés de la classe Thread :

属性描述
CurrentContext获取线程正在其中执行的当前上下文。
CurrentCulture获取或设置当前线程的区域性。
CurrentPrinciple获取或设置线程的当前负责人(对基于角色的安全性而言)。
CurrentThread获取当前正在运行的线程。
CurrentUICulture获取或设置资源管理器使用的当前区域性以便在运行时查找区域性特定的资源。
ExecutionContext获取一个 ExecutionContext 对象,该对象包含有关当前线程的各种上下文的信息。
IsAlive获取一个值,该值指示当前线程的执行状态。
IsBackground获取或设置一个值,该值指示某个线程是否为后台线程。
IsThreadPoolThread获取一个值,该值指示线程是否属于托管线程池。
ManagedThreadId获取当前托管线程的唯一标识符。
Name获取或设置线程的名称。
Priority获取或设置一个值,该值指示线程的调度优先级。
ThreadState获取一个值,该值包含当前线程的状态。

Le tableau suivant répertorie quelques méthodes couramment utilisées de la classe Thread :

Numéro de sérieNom et description de la méthode
1public void Abort( )
Lance une ThreadAbortException sur le thread appelant cette méthode pour commencer le processus de terminaison de ce thread. L’appel de cette méthode termine généralement le thread.
2public static LocalDataStoreSlot AllocateDataSlot()
Allouer des emplacements de données sans nom sur tous les threads. Pour de meilleures performances, utilisez plutôt les champs marqués avec l’attribut ThreadStaticAttribute.
3public statique LocalDataStoreSlot AllocateNamedDataSlot( nom de chaîne)
Allouez des emplacements de données nommés sur tous les threads. Pour de meilleures performances, utilisez plutôt les champs marqués avec l’attribut ThreadStaticAttribute.
4public static void BeginCriticalRegion()
Avertit l'hôte que l'exécution est sur le point d'entrer dans une zone de code dans laquelle le thread se termine Ou l'impact d'une exception non gérée peut nuire à d'autres tâches dans le domaine d'application.
5public static void BeginThreadAffinity()
Notifie le code géré par l'hôte qu'il est sur le point d'exécuter un thread qui dépend de l’identité de l’instruction physique actuelle du système d’exploitation.
6public static void EndCriticalRegion()
Avertit l'hôte que l'exécution est sur le point d'entrer dans une zone de code dans laquelle le thread se termine Ou les exceptions non gérées n'affectent que la tâche en cours.
7public static void EndThreadAffinity()
Notifier l'hôte que le code géré a fini de s'exécuter dépend de l'identité de l'hôte actuel instructions de thread du système d’exploitation physique.
8public static void FreeNamedDataSlot(string name)
Élimine l'association entre le nom et l'emplacement pour tous les threads du processus . Pour de meilleures performances, utilisez plutôt les champs marqués avec l’attribut ThreadStaticAttribute.
9Objet statique public GetData( Emplacement LocalDataStoreSlot )
Récupère une valeur de l'emplacement spécifié sur le thread actuel dans le domaine actuel du thread actuel. Pour de meilleures performances, utilisez plutôt les champs marqués avec l’attribut ThreadStaticAttribute.
10public static AppDomain GetDomain()
Renvoie le domaine actuel dans lequel le thread actuel est en cours d'exécution.
11public static AppDomain GetDomainID()
Renvoie un identifiant de domaine d'application unique.
12public statique LocalDataStoreSlot GetNamedDataSlot( nom de chaîne )
Trouvez un emplacement de données nommé. Pour de meilleures performances, utilisez plutôt les champs marqués avec l’attribut ThreadStaticAttribute.
13public void Interrupt()
Interrompre le thread dans l'état du thread WaitSleepJoin.
14public void Join()
Bloque le thread appelant jusqu'à ce que l'un des threads se termine tandis que le traitement standard de la pompe à messages COM et SendMessage se poursuit. Il existe différentes surcharges de cette méthode.
15public static void MemoryBarrier()
Synchronisez l'accès à la mémoire comme suit : Le processeur exécutant le thread en cours Lorsque les instructions sont réorganisées , l'accès à la mémoire après l'appel MemoryBarrier ne peut pas être effectué en premier, puis l'accès à la mémoire avant l'appel à MemoryBarrier.
16public static void ResetAbort()
Annuler l'abandon demandé pour le fil de discussion en cours.
17public static void SetData( Emplacement LocalDataStoreSlot, Données d'objet )
Définissez les données dans l'emplacement spécifié pour le domaine actuel de ce fil sur le fil en cours d'exécution. Pour de meilleures performances, utilisez plutôt les champs marqués avec l’attribut ThreadStaticAttribute.
18public void Start()
Démarrer un fil de discussion.
19public statique vide Sommeil( int millisecondesTimeout )
Laissez le fil s'arrêter un moment.
20public static void SpinWait( itérations int )
fait attendre le thread pendant la durée définie par le paramètre itérations.
21octet statique public VolatileRead( adresse d'octet de référence )
double statique publique VolatileRead( réf double adresse )
public static int VolatileRead( adresse de référence )
Objet statique public VolatileRead( Adresse de l'objet ref )

Lire la valeur du champ. Cette valeur est la valeur la plus récente écrite par n'importe quel processeur de l'ordinateur, quel que soit le nombre de processeurs ou l'état du cache du processeur. Il existe différentes surcharges de cette méthode. Seuls quelques formulaires sont donnés ici.
22public static void VolatileWrite( adresse d'octet de référence, valeur d'octet )
public static void VolatileWrite( réf double adresse, valeur double )
public static void VolatileWrite( ref int adresse, valeur entière )
public static void VolatileWrite( ref Adresse de l'objet, Valeur de l'objet )

Écrit immédiatement une valeur dans un champ, rendant la valeur visible à tous les processeurs de l'ordinateur. Il existe différentes surcharges de cette méthode. Seuls quelques formulaires sont donnés ici.
23public static bool Yield()
Fait en sorte que le thread appelant exécute un autre thread prêt à s'exécuter sur le thread actuel. processeur. Le système d'exploitation sélectionne le thread à exécuter.

Création de fils de discussion

Les fils de discussion sont créés en étendant la classe Thread. La classe Thread étendue appelle la méthode Start() pour démarrer l'exécution du thread enfant.

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 ci-dessus est compilé et exécuté, il produit les résultats suivants :

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 l'utilisation de la méthode sleep(), qui est utilisée pour mettre un fil de discussion en pause à un moment précis.

using System;
using System.Threading;

namespace MultithreadingApplication
{
    class ThreadCreationProgram
    {
        public static void CallToChildThread()
        {
            Console.WriteLine("Child thread starts");
            // 线程暂停 5000 毫秒
            int sleepfor = 5000; 
            Console.WriteLine("Child Thread Paused for {0} seconds", 
                              sleepfor / 1000);
            Thread.Sleep(sleepfor);
            Console.WriteLine("Child thread resumes");
        }
        
        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 ci-dessus est compilé et exécuté, il produira les résultats suivants :

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

Détruire le fil

Abort() la méthode est utilisé Détruire le fil.

Abandonnez un thread au moment de l'exécution en lançant threadabortexception. Cette exception ne peut pas être interceptée. S'il y a un bloc finally, le contrôle sera envoyé au bloc finally.

Le programme suivant illustre ceci :

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 ci-dessus est compilé et exécuté, il produit les résultats suivants :

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

Site Web PHP chinois