Share via


Threading managé et non managé dans Microsoft Windows

Mise à jour : novembre 2007

La gestion de tous les threads s'effectue par l'intermédiaire de la classe Thread y compris les threads créés par le Common Language Runtime et ceux créés en dehors du runtime et qui entrent dans l'environnement managé pour y exécuter du code. Le runtime surveille tous les threads de son processus et qui ont exécuté du code au sein de l'environnement d'exécution managé. Il n'assure le suivi d'aucun autre thread. Les threads peuvent entrer dans l'environnement d'exécution managé via COM Interop (car le runtime expose les objets managés à l'environnement managé en tant qu'objets COM), la fonction DllGetClassObject() COM et l'appel de code non managé.

Lorsqu'un thread non managé entre dans le runtime par l'intermédiaire, par exemple, d'un wrapper CCW (COM Callable Wrapper), le système vérifie le stockage local des threads de ce thread à la recherche d'un objet Thread interne managé. Si cette recherche aboutit, le runtime a déjà connaissance de ce thread. Cependant, si la recherche n'aboutit pas, le runtime crée un nouvel objet Thread et l'installe dans le stockage local des threads de ce thread.

Dans le threading managé, Thread.GetHashCode représente l'identification de thread managé stable. Durant la durée de vie de votre thread, celui-ci n'entrera pas en conflit avec la valeur d'un autre thread, quel que soit le domaine d'application dont cette valeur provient.

Remarque :

Un ThreadId de système d'exploitation n'a pas de relation fixe avec un thread managé, car un hôte non managé peut contrôler la relation entre les threads managés et non managés. Plus particulièrement, un hôte élaboré peut utiliser l'API Fiber pour planifier de nombreux threads managés par rapport au même thread de système d'exploitation, ou pour déplacer un thread managé entre les différents threads de système d'exploitation.

Mappage à partir du threading Win32 vers le threading managé

Le tableau suivant mappe les éléments du threading Win32 à leur équivalent runtime approximatif. Remarquez que ce mappage ne représente pas des fonctionnalités identiques. Par exemple, TerminateThread n'exécute pas de clauses finally ou ne libère pas de ressources, et ne peut pas être inhibé. Toutefois, Thread.Abort exécute tout votre code de restauration, récupère toutes les ressources, et peut être refusé à l'aide de ResetAbort. Veillez à bien lire la documentation avant de faire des hypothèses sur vos fonctionnalités.

Dans Win32

Dans le Common Language Runtime

CreateThread

Combinaison de Thread et ThreadStart

TerminateThread

Thread.Abort

SuspendThread

Thread.Suspend

ResumeThread

Thread.Resume

Sleep

Thread.Sleep

WaitForSingleObject sur le handle du thread

Thread.Join

ExitThread

Pas d'équivalent

GetCurrentThread

Thread.CurrentThread

SetThreadPriority

Thread.Priority

Pas d'équivalent

Thread.Name

Pas d'équivalent

Thread.IsBackground

Proche de CoInitializeEx (OLE32.DLL)

Thread.ApartmentState

Threads managés et cloisonnements (apartments) COM

Un thread managé peut être marqué pour indiquer qu'il hébergera un thread cloisonné (STA, Single-Threaded Apartment) ou MTA (Multithreaded Apartment). Les méthodes GetApartmentState, SetApartmentState et TrySetApartmentState de la classe Thread retournent et assignent l'état de cloisonnement d'un chemin. Si l'état n'a pas été défini, GetApartmentState retourne ApartmentState.Unknown.

Remarque :

Dans les versions 1.0 et 1.1 du .NET Framework, la propriété ApartmentState est utilisée pour obtenir et définir l'état de cloisonnement.

Cette propriété peut être définie uniquement lorsque le thread possède l'état ThreadState.Unstarted ; elle ne peut être définie qu'une fois pour un thread.

Si l'état de cloisonnement est défini avant le début du thread, le thread est initialisé comme une cloison multithread (MTA). Le thread finaliseur et tous les threads contrôlés par ThreadPool sont des MTA (multithread apartment).

Remarque importante :

Pour le code de démarrage d'application, la seule façon de contrôler l'état de cloisonnement consiste à appliquer MTAThreadAttribute ou STAThreadAttribute à la procédure de point d'entrée. Dans les versions 1.0 et 1.1 du .NET Framework, la propriété ApartmentState peut être définie comme première ligne de code. Ce n'est pas autorisé dans la version 2.0 du .NET Framework.

Les objets managés qui sont exposés à COM se comportent comme s'ils avaient agrégé le marshaleur libre de threads (FTM). Autrement dit, ils peuvent être appelés à partir de n'importe quel cloisonnement (apartment) COM en mode libre de threads. Les seuls objets managés qui n'adoptent pas ce comportement libre de threads sont les objets dérivés à partir de ServicedComponent.

Dans les environnements managés, il n'y a pas de prise en charge pour SynchronizationAttribute sauf si vous utilisez des instances de contexte et des instances managées liées au contexte. Si vous utilisez EnterpriseServices, votre objet doit, dans ce cas, dériver de ServicedComponent (qui lui-même dérive de ContextBoundObject).

Lorsque le code managé appelle des objets COM, il observe toujours les règles COM. En d'autres termes, il appelle via les proxies cloisonnés COM et les wrappers de contexte COM+ 1.0 comme le dicte OLE32.

Problèmes de blocage

Si un thread effectue un appel non managé dans le système d'exploitation qui a bloqué le thread dans du code non managé, le runtime n'en prend pas le contrôle pour Thread.Interrupt ou Thread.Abort. Dans le cas de Thread.Abort, le runtime marque le thread pour Abort et en prend le contrôle lorsqu'il rentre dans du code managé. Il est préférable que vous utilisiez le blocage managé plutôt que le blocage non managé. WaitHandle.WaitOneWaitHandle.WaitAny, WaitHandle.WaitAll, Monitor.Enter, Monitor.TryEnter, Thread.Join, GC.WaitForPendingFinalizers, etc. réagissent tous à Thread.Interrupt et à Thread.Abort. Par ailleurs, si votre thread est dans un thread cloisonné (STA, Single-Threaded Apartment), toutes ces opérations de blocage managées pomperont correctement des messages dans votre STA pendant que votre thread est bloqué.

Voir aussi

Référence

Thread.ApartmentState

Énumération Threadstate

ServicedComponent

Thread

Monitor