Partager via


appartements Single-Threaded

L’utilisation d’appartements à thread unique (processus de modèle d’appartement) offre un paradigme basé sur les messages pour traiter simultanément plusieurs objets. Il vous permet d’écrire du code plus efficace en autorisant un thread, pendant qu’il attend la fin d’une opération fastidieuse, pour permettre à un autre thread d’être exécuté.

Chaque thread d’un processus initialisé en tant que processus de modèle d’appartement et qui récupère et répartit les messages de fenêtre, est un thread d’appartement à thread unique. Chaque fil vit dans son propre appartement. Dans un appartement, les pointeurs d’interface peuvent être passés sans marshaling, et par conséquent, tous les objets d’un thread d’appartement à thread unique communiquent directement.

Un regroupement logique d’objets associés qui s’exécutent tous sur le même thread, et doit donc avoir une exécution synchrone, peut vivre sur le même thread d’appartement à thread unique. Toutefois, un objet de modèle d’appartement ne peut pas résider sur plusieurs threads. Les appels aux objets dans d’autres threads doivent être effectués dans le contexte du thread propriétaire, de sorte que les threads COM distribués basculent automatiquement lorsque vous appelez un proxy.

Les modèles interprocess et interthread sont similaires. Quand il est nécessaire de passer un pointeur d’interface à un objet d’un autre appartement (sur un autre thread) au sein du même processus, vous utilisez le même modèle de marshaling que les objets dans différents processus utilisent pour passer des pointeurs entre les limites du processus. En obtenant un pointeur vers l’objet de marshaling standard, vous pouvez marshaler des pointeurs d’interface entre les limites de thread (entre appartements) de la même façon que vous effectuez entre les processus. (Les pointeurs d’interface doivent être marshalés lorsqu’ils sont passés entre appartements.)

Les règles relatives aux appartements à thread unique sont simples, mais il est important de les suivre attentivement :

  • Chaque objet ne doit vivre que sur un seul thread (dans un appartement à thread unique).
  • Initialisez la bibliothèque COM pour chaque thread.
  • Marshalez tous les pointeurs vers les objets lors de leur passage entre appartements.
  • Chaque appartement à thread unique doit avoir une boucle de message pour gérer les appels provenant d’autres processus et appartements au sein du même processus. Les appartements à thread unique sans objets (client uniquement) ont également besoin d’une boucle de message pour distribuer les messages de diffusion utilisés par certaines applications.
  • Les objets dll ou in-process n’appellent pas les fonctions d’initialisation COM ; Au lieu de cela, ils inscrivent leur modèle de thread avec la ThreadingModel nommée sous la clé InprocServer32 dans le Registre. Les objets prenant en compte l’appartement doivent également écrire soigneusement des points d’entrée DLL. Il existe des considérations spéciales qui s’appliquent aux serveurs en cours de traitement. Pour plus d’informations, consultez In-Process problèmes de thread de serveur.

Bien que plusieurs objets puissent vivre sur un seul thread, aucun objet de modèle d’appartement ne peut vivre sur plusieurs threads.

Chaque thread d’un processus client ou d’un serveur hors processus doit appeler CoInitialize, ou appeler CoInitializeEx et spécifier COINIT_APARTMENTTHREADED pour le paramètre dwCoInit. L’appartement principal est le thread qui appelle CoInitializeEx en premier. Pour plus d’informations sur les serveurs in-process, consultez In-Process Problèmes de thread de serveur.

Tous les appels à un objet doivent être effectués sur son thread (dans son appartement). Il est interdit d’appeler un objet directement à partir d’un autre thread ; l’utilisation d’objets de cette manière libre-thread peut entraîner des problèmes pour les applications. L’implication de cette règle est que tous les pointeurs vers les objets doivent être marshalés lorsqu’ils sont passés entre appartements. COM fournit les deux fonctions suivantes à cet effet :

Ces fonctions encapsulent les appels à CoMarshalInterface et fonctions CoUnmarshalInterface, qui nécessitent l’utilisation de l’indicateur de MSHCTX_INPROC.

En général, le marshaling est effectué automatiquement par COM. Par exemple, lors du passage d’un pointeur d’interface en tant que paramètre dans un appel de méthode sur un proxy vers un objet d’un autre appartement ou lors de l’appel de CoCreateInstance, COM effectue automatiquement le marshaling. Toutefois, dans certains cas spéciaux, où l’enregistreur d’application transmet des pointeurs d’interface entre des appartements sans utiliser les mécanismes COM normaux, l’enregistreur doit gérer le marshaling manuellement.

Si un appartement (Appartement 1) dans un processus a un pointeur d’interface et un autre appartement (Apartment 2) nécessite son utilisation, Apartment 1 doit appeler CoMarshalInterThreadInterfaceInStream pour marshaler l’interface. Le flux créé par cette fonction est thread-safe et doit être stocké dans une variable accessible par Apartment 2. L’appartement 2 doit passer ce flux à CoGetInterfaceAndReleaseStream pour annuler lamarshalisation de l’interface et récupérer un pointeur vers un proxy via lequel il peut accéder à l’interface. L’appartement principal doit rester actif jusqu’à ce que le client ait terminé tout le travail COM (car certains objets in-process sont chargés dans l’appartement principal, comme décrit dans In-Process Problèmes de thread de serveur). Une fois qu’un objet a été passé entre les threads de cette façon, il est très facile de passer des pointeurs d’interface en tant que paramètres. De cette façon, distributed COM effectue le marshaling et le basculement de thread pour l’application.

Pour gérer les appels d’autres processus et appartements au sein du même processus, chaque appartement à thread unique doit avoir une boucle de message. Cela signifie que la fonction de travail du thread doit avoir une boucle GetMessage/DispatchMessage. Si d’autres primitives de synchronisation sont utilisées pour communiquer entre les threads, la fonction MsgWaitForMultipleObjects peut être utilisée pour attendre les messages et les événements de synchronisation de threads. La documentation de cette fonction présente un exemple de ce type de boucle de combinaison.

COM crée une fenêtre masquée à l’aide de la classe Windows « OleMainThreadWndClass » dans chaque appartement à thread unique. Un appel à un objet est reçu en tant que message de fenêtre pour cette fenêtre masquée. Lorsque l’appartement de l’objet récupère et distribue le message, la fenêtre masquée la reçoit. La procédure de fenêtre appelle ensuite la méthode d’interface correspondante de l’objet.

Lorsque plusieurs clients appellent un objet, les appels sont mis en file d’attente dans la file d’attente des messages et l’objet reçoit un appel chaque fois que son appartement récupère et distribue des messages. Étant donné que les appels sont synchronisés par COM et que les appels sont toujours remis par le thread qui appartient à l’appartement de l’objet, les implémentations d’interface de l’objet n’ont pas besoin de fournir de synchronisation. Les appartements à thread unique peuvent implémenter IMessageFilter pour leur permettre d’annuler des appels ou de recevoir des messages de fenêtre si nécessaire.

L’objet peut être recréé si l’une de ses implémentations de méthode d’interface récupère et distribue des messages ou effectue un appel ORPC à un autre thread, ce qui entraîne la remise d’un autre appel à l’objet (par le même appartement). OLE n’empêche pas la réentrance sur le même thread, mais elle peut aider à assurer la sécurité des threads. Cela est identique à la façon dont une procédure de fenêtre peut être réinitielle si elle récupère et distribue des messages lors du traitement d’un message. Toutefois, l’appel d’un serveur d’appartement monothread hors processus qui appelle un autre serveur d’appartement à thread unique permet au premier serveur d’être entré.

accès aux interfaces entre appartements

choix du modèle de threading

appartements multithreads

Problèmes de thread de serveur In-Process

processus , threads et appartements

Single-Threaded et de communication multithread