2009-11-06 6 views
9

Il semble que lorsqu'un thread est créé à partir de DllMain sur DLL_PROCESS_ATTACH il ne commencera pas tant que toutes les DLL n'ont pas été chargées. Comme j'ai besoin de m'assurer que le thread s'exécute avant de continuer, je me retrouve dans une impasse. Est-il possible de forcer le fil à démarrer?Création d'un thread dans DllMain?

Répondre

10

Vous ne devriez pas faire des appels API, en particulier pour des choses comme la création de fils ou de fenêtres, de DLLMain. Raymond Chen a écrit à ce sujet plusieurs fois; voici one qui est particulièrement pertinent.

+10

CreateThread est l'une des rares choses que vous pouvez faire dans DllMain, parce que c'est un appel à kernel32 qui est garanti d'être déjà chargé. –

+2

@Ben Voigt mais soyez extrêmement prudent, car il est facile d'obtenir dead-lock si l'appel DllMain actuel est demandé d'attendre le retour du nouveau thread. – mloskot

+0

@mloskot: Appeler les fonctions d'attente dans 'DllMain' est très mauvais, peu importe le type d'objet que vous attendez. En règle générale, tout thread qui exécute du code à partir d'une DLL doit avoir un compte de référence sur cette DLL, moins le code obtenu en dessous. Ce qui empêche le problème de se produire, puisque DllMain ne sera pas appelé (pour le processus de détachement) tant que le thread est en cours d'exécution. –

5

Non. Vous ne devez pas appeler CreateThread (ou toute variante) à partir de DllMain. Tenter de synchroniser entraînera un blocage. Qu'est-ce que vous essayez de faire exactement?

Best Practices for Creating DLLs

+7

Rien de mal à appeler CreateThread, mais il n'y a aucun moyen de contourner le fait que le thread sera suspendu jusqu'à ce que le traitement DllMain se termine dans le thread parent. –

0

Vous demandez des problèmes si vous faites cela. Vous ne devriez faire aucun appel (directement ou indirectement) à des fonctions qui sont en dehors de votre DLL (y compris les appels de bibliothèque C, etc.).

Si vous ne pouvez pas modifier la DLL que vous avez (par exemple vous n'avez pas de code source), peut être en mesure de s'en tirer si votre DLL est chargée dynamiquement après le reste de vos DLL dépendantes initialisé. Je ne recommanderais pas cette approche si vous pouvez l'éviter car trouver la chaîne de dépendances n'est pas toujours trivial (par exemple si votre dll fait qu'une DLL dépendante en charge dynamiquement un troisième via COM ou d'autres moyens).

+2

Le premier paragraphe est une sur-généralisation. Il est parfaitement possible de faire des appels dans des DLL que vous connaissez pour un fait déjà chargé avant le vôtre. En général et dans la plupart des situations, cela signifie que KERNEL32.DLL seulement, ce qui peut sembler une limitation paralysante, mais vous pouvez l'utiliser pour vous sortir de cette situation. –

+2

http://blogs.msdn.com/oldnewthing/archive/2007/09/04/4731478.aspx –

+0

Thanks Integer Poet. Cela répond exactement à la question que je suis venu ici pour résoudre. –

5

Que fait votre thread?

Si vous essayez de déplacer des éléments sur un deuxième thread pour éviter les restrictions sur ce que vous pouvez faire dans DllMain, pas de chance. Ce ne sont pas des restrictions sur ce que DllMain peut faire, ce sont des restrictions sur ce qui peut être fait pendant que DllMain est en cours d'exécution (et détient le verrou du chargeur). Si votre thread doit prendre le verrou du chargeur, il attendra que le premier thread finisse de l'utiliser. Si votre thread n'avait pas besoin du verrou du chargeur, je ne vois pas pourquoi il ne pourrait pas continuer immédiatement ... mais il n'y a pas de thread qui n'a pas besoin du verrou du chargeur. Windows doit envoyer des messages DLL_THREAD_ATTACH à toutes les DLL avant que votre thread puisse commencer à s'exécuter, ce qui signifie qu'il appelle également votre propre DllMain et que Windows protège contre la ré-entrée.

Il n'y a pas moyen de contourner cela. Le thread ne peut pas démarrer avant le traitement DLL_THREAD_ATTACH, et cela ne peut pas se produire lorsque votre premier thread est dans DllMain. La seule solution possible consiste à lancer un nouveau processus (qui possède un verrou de chargeur indépendant et ne bloquera pas l'attente de la vôtre).

+0

J'ai essayé un simple exercice d'utilisation de 'CreateThread()' pour une fonction de travail très simple dans un 'DLLMain()' pendant le traitement d'un message 'DLL_PROCESS_ATTACH'. La fonction thread utilisait 'Sleep()' pendant 1000 millisecondes. Tout a bien fonctionné. J'ai pu voir les messages 'DLL_THREAD_ATTACH' et les messages' DLL_THREAD_DETACH' du thread initial faisant le 'DLL_PROCESS_ATTACH' et le fil créé pendant le traitement d'attachement. Cependant, ce thread de travail n'a rien fait d'autre que 'Sleep()'. Les appels Kernel32.dll sont censés être bien. Testé avec VS 2005 Windows 7. –

+0

Assez curieusement, c'est vraiment la seule réponse qui répond à la question qui a été posée. Je ne sais pas pourquoi le PO a décidé d'accepter une réponse qui ne l'est pas. – IInspectable

Questions connexes