2009-12-26 2 views
6

Je souhaite lancer un thread séparé pour gérer les messages de la fenêtre (via une boucle GetMessage bloquante), mais créer les fenêtres dans le thread initial, par la suite.Comment puis-je gérer les messages de fenêtre à partir d'un thread séparé?

Dans le thread séparé, dès qu'il lance, je fais appel PeekMessage avec PM_NOREMOVE pour assurer une file d'attente de messages existe (est-ce nécessaire?), Suivi ..

AttachThreadInput(initial thread id,GetCurrentThreadId(),true) 

..before enfin entrer la boucle de message

Je n'utilise pas encore de mutex ou de cs pour m'assurer que cela se produit dans le temps, mais j'utilise simplement une instruction Sleep dans mon thread initial pour des raisons de simplicité. Quoiqu'il en soit, les messages de fenêtre ne semblent pas être interceptés par le thread séparé.

Je ne suis pas certain de savoir si je le fais correctement et j'apprécierais tout conseil possible. Les deux fils sont dans le même processus

Merci à tous

+1

C'est presque toujours une idée terrible. Pour commencer, vous voulez probablement gérer les messages * qui ne sont pas réellement publiés * dans la file d'attente d'entrée du thread de l'interface utilisateur ... A défaut, vous voudrez au moins * envoyer * des messages aux fenêtres appartenant au thread de l'interface utilisateur. ne fonctionnera pas non plus. Vraiment, vous devriez traiter les messages sur le thread de l'interface utilisateur et utiliser le thread séparé pour les opérations qui prennent du temps, sans essayer de partager la file d'attente d'entrée entre eux. Voir: http://stackoverflow.com/questions/783073/processing-messages-is-too-slow-resulting-in-a-jerky-unresponsive-ui-how-can – Shog9

+0

Pour toutes fins utiles, je souhaite utiliser le fil séparé comme le fil d'interface utilisateur. Je souhaite juste avoir la possibilité d'initier la création de la fenêtre à partir du – ProPuke

+0

@ProPuke primaire: et vous ne pouvez pas faire cela. Windows doit être détenu et manipulé par un * et un seul thread *: l'ensemble du système est conçu avec cette hypothèse. – Shog9

Répondre

2

Il semble que la meilleure façon d'inciter la création de fenêtre à partir du thread principal, tout en ayant des messages pour les traiter dans un fil distinct en boucle est d'utiliser un message personnalisé, qui peut être envoyé au thread séparé créer la fenêtre, mais en permettant que l'action à appeler à partir du fil initial:

1) Allouer un message personnalisé et créer une structure pour maintenir les paramètres d'initialisation de la fenêtre:

message_create_window = WM_USER + 0; 
class Message_create_window{ 
    Message_create_window(...); 
}; 

2) au lieu de appeler CreateWindow (Ex), utiliser quelque chose de similaire à ce qui suit, en passant dans le relavant paramètres de création de fenêtre:

PostThreadMessage(
    thread.id, 
    message_create_window, 
    new Message_create_window(...), 
    0 
); 

3) Gérer le message personnalisé dans la pompe de message de votre fil de manutention ui, extraire les paramètres de création, & libre après:

MSG msg; 
GetMessage(&msg,0,0,0); 
... 
switch(msg->message){ 
    ... 
    case message_create_window:{ 
     Message_create_window *data=msg->wParam; 
     CreateWindowEx(data->...); 
     delete data; 
    }break; 
    ... 

Toutefois, cela ne, ont la effets secondaires suivants:

  • La fenêtre sera créée de manière asynchrone.S'il est nécessaire que le bloc de thread initial jusqu'à ce que la fenêtre soit créée (ou, en fait, que l'existence de la fenêtre puisse être affirmée), un outil de synchronisation de threads doit être utilisé (tel qu'un événement)
  • interagir avec la fenêtre (il s'agit d'une application multithread, après tout)

S'il y a des trous majeurs dans cette réponse, ou cela semble être une approche terrible, s'il vous plaît corrigez-moi. (C'est toujours ma question, & J'essaie de trouver le meilleur moyen d'accomplir cela)

7

Ce n'est pas ce que AttachThreadInput fait. Même après avoir attaché votre file d'attente d'entrée à un autre thread, Windows a toujours une affinité de thread. Les messages dans la file d'attente pour une fenêtre donnée peuvent uniquement être supprimés de la file d'attente par le thread de cette fenêtre.

Ce que fait AttachTheadInput consiste à faire partager à deux threads une file d'attente d'entrée. Cela leur permet d'interroger des informations sur l'état d'entrée et de savoir que l'autre thread obtiendra la même réponse pour la même requête. Par exemple, un thread pourrait appeler GetAsyncKeyState et savoir que la réponse reflétait l'état de la clé pour l'autre thread.

Il permet à deux ou plusieurs threads d'avoir la même relation à la file d'attente d'entrée et les uns par rapport aux autres que les processus dans Windows 3x. C'est la raison pour laquelle cette API existe; de sorte que les applications multiprocessus complexes puissent être portées de Win 3x à Win95/WinNT.

+0

Ahh je vois. J'avais mal interprété le but des fonctions. J'ai effectivement basé l'hypothèse originale sur la réponse suivante: http://stackoverflow.com/questions/617248/can-the-hwnd-from-createwindow-createdialog-be-getmessaged-from-another-thread/621631#621631 Connaissez-vous d'autres moyens de réaliser cette fonctionnalité? – ProPuke

+0

Demandez au thread d'origine de gérer la file d'attente, et le nouveau thread fait ce que vous voulez que le thread d'origine fasse. Sinon, créez toutes vos fenêtres sur le nouveau thread. –

Questions connexes