Ändern des Nachrichten-Loop-Threads eines Fensters

8

Kürzlich habe ich versucht, die Nachrichtenschleife eines Fensters in einen eigenen Thread einzufügen, und ich habe mich gefragt, warum er nie Nachrichten erhalten hat, aber ich habe erfahren, dass Windows Nachrichten an den Thread schreibt, der das Fenster erstellt hat. Wie erstellen Sie ein Fenster in einem Thread und verursachen, dass ein anderer Thread die Nachrichten dieses Fensters empfängt? Ich habe die PostThreadMessage-Funktion gesehen, aber ich glaube, dass es auch für den Thread, der das Fenster erstellt hat, auf Nachrichten warten muss, was genau das ist, was ich vermeiden möchte, so dass die Funktion nicht das ist, was ich brauche.

Es scheint, als wäre das eine häufige Frage, und ich habe ziemlich viel Zeit damit verbracht, nach einer Antwort zu suchen, aber ich kann keine finden.

    
Epro 03.12.2010, 16:07
quelle

5 Antworten

11
  

Wie erstellen Sie ein Fenster in einem?   fädeln und einen anderen Thread verursachen   die Nachrichten dieses Fensters empfangen?

Einfache Antwort ... Sie nicht. Erstellen Sie das Fenster des Threads, dessen Nachrichten Sie verarbeiten möchten. Wenn dies nicht möglich ist, müssen Sie Ihre Vorgehensweise überdenken.

    
Goz 03.12.2010 16:11
quelle
7

Die Windows-Nachrichtenpumpe ist wirklich nur eine while -Schleife, die Nachrichten aus einer Warteschlange mit PeekMessage() abruft und die Windows WndProc-Funktion aufruft. Es gibt ein wenig mehr als das, aber das ist die grundlegende Operation.

Somit ist der Thread, in den die while -Schleife läuft, der einzige Thread, in dem Ihre Windows "laufen" können. So ist jede Windows-Anwendung, die ich je gesehen habe, aufgebaut.

Allerdings habe ich in der Vergangenheit gedacht, dass es mit einigem Aufwand möglich sein sollte, eine Windows-App mit Fenstern in mehreren Threads zu erstellen. Ich habe keinen Code, um es dir zu zeigen, weil es lange her ist, dass ich darüber nachgedacht habe, aber es gab zwei Ansätze, die ich in Betracht gezogen habe:

  1. Behalten Sie eine Nachrichtenpumpe im Hauptthread. Ändern Sie jedoch den Nachrichtenpumpenkode so, dass er in while Nachrichten an Worker-Threads unter Verwendung von QueueUserAPC basierend auf dem Thread, in dem HWND ausgeführt wird, versendet. Hierfür wäre eine Lookup-Map erforderlich, die rechenintensiv sein kann .

  2. Erstellen Sie eine ganz neue Nachrichtenpumpe in einem Worker-Thread. Sie müssten alle while Code schreiben, aber das ist einfach genug, und Petzolds klassisches Buch wird geben Sie alle Werkzeuge, die Sie dazu benötigen.

Beachten Sie, dass dieser Ansatz aus architektonischer Sicht für jede Anwendung, die mir einfällt, keinen Sinn ergibt. Sie brauchen einfach keine Fenster, um in mehreren Threads zu laufen, wenn Sie Ihre App vernünftig erstellen. Die Fensterbehandlung erfolgt in einem Thread, Operationen in einem anderen (oder vielen). Ich hatte jedoch ein interessantes Forschungsgebiet, und das hat mich auf diesem Weg geführt. Lange Rede, kurzer Sinn, ich bin mir praktisch sicher, dass du das nicht tun musst und nicht tun solltest - aber das könnte sein, wie du es machen würdest.

    
John Dibling 03.12.2010 16:21
quelle
5

Es ist nicht möglich. Jedes Fenster gehört zu dem Thread, der es erstellt hat, und dieser Besitz kann nicht übertragen werden.

Es geht nicht darum, Ihre Nachrichtenpumpe in einen anderen Thread zu packen. Jeder Thread hat seine eigene Nachrichtenwarteschlange. Wenn Sie eine Nachricht an ein Fenster senden oder senden, prüft das Betriebssystem, welcher Thread das Fenster besitzt und leitet die Nachricht an die Nachrichtenwarteschlange dieses Threads weiter. Threads können keine Nachrichtenwarteschlange lesen, sondern ihre eigenen, sodass Sie die Nachrichten der Fenster eines anderen Threads nicht mit einem Thread verarbeiten können.

Sie könnten Nachrichten an einen anderen Thread weiterleiten, wie in erste Idee in Johns Antwort , aber als Universal-Message-Handler wird das komplizierter, als es wert ist. Viele Nachrichten sollen den Status des Fensters ändern, aber Sie können den Status nur vom eigenen Thread des Fensters aus ändern. Einige Nachrichten werden mit der Absicht gesendet, einen sinnvollen Rückgabewert zu erhalten, aber Sie können nicht wissen, was zurückgegeben werden soll, bis die Nachricht verarbeitet wurde. Sie müssen also blockieren und warten, bis der Worker-Thread die Nachricht verarbeitet hat. p>

Sie sollten besser die kleinen Nachrichten identifizieren, die wirklich in einen Worker-Thread geladen werden können, und sie speziell behandeln. Sobald Sie das tun, werden Sie nicht wirklich ein Fenster haben, dessen Nachrichten in einem anderen Thread behandelt werden; Sie werden nur einen normalen Worker-Thread haben, und es wird viel weniger verwirrend sein, darüber nachzudenken.

Wenn Nachrichten an Ihr Fenster gesendet werden, die viel Zeit für die Verarbeitung benötigen, aber der Absender entweder das Ergebnis nicht kennen muss oder Sie das Ergebnis kennen, bevor Sie die Verarbeitung beenden Dann können Sie eine frühe Antwort geben, indem Sie ReplyMessage aufrufen . Dadurch kann der sendende Thread weiter ausgeführt werden, während der Thread des Fensters zusätzliche Arbeit leistet.

    
Rob Kennedy 03.12.2010 18:25
quelle
2

Sie können sehen, ob AttachThreadInput funktioniert für Sie - Sie können Nachrichten von anderen Threads verarbeiten.

Das ist wirklich nicht so üblich für eine Frage, weil Sie fast immer eine Windows-Nachricht in dem Thread behandeln, in dem sie erstellt wurde. Siehe Goz 'Antwort; Ich stimme zu.

Beachten Sie, dass Sie nichts davon erhalten, wenn Sie die Nachrichtenverarbeitung in einen anderen Thread einfügen. Zerlegen Sie GUI-Aufgaben nicht in mehrere Threads, sondern trennen Sie Verarbeitungs- / Hintergrundaufgaben in Threads.

    
tenfour 03.12.2010 16:12
quelle
-2

Siehe dies:

msdn: Ссылка

Der Thread, zu dem die Nachricht gepostet wird, muss eine Nachrichtenwarteschlange erstellt haben, oder andernfalls Aufruf an PostThreadMessage schlägt fehl. Verwenden Sie die folgende Methode, um diese Situation zu behandeln.

1. Erstellen Sie ein Ereignisobjekt und erstellen Sie dann den Thread.

2.Verwenden Sie die WaitForSingleObject-Funktion, um zu warten, dass das Ereignis vor dem Aufruf von PostThreadMessage auf den signalisierten Status gesetzt wird.

3.In dem Thread, an den die Nachricht gesendet wird, rufen Sie PeekMessage wie hier gezeigt auf, um das System zu zwingen, die Nachrichtenwarteschlange zu erstellen.

%Vor%

4.Stellen Sie das Ereignis ein, um anzuzeigen, dass der Thread bereit ist, veröffentlichte Nachrichten zu empfangen.

    
qinhaihong 26.04.2013 13:26
quelle