Delphi Multi-Threading-Nachrichtenschleife

8

Meine Anwendung hat mehrere Threads: 1) Hauptgewinde 2) 2 Sub-Main Threads (jeweils mit Message Loop, wie unten gezeigt), die von TFQM verwendet werden 3) n Worker Threads (einfache Schleife, mit Sleep ())

Mein Problem besteht darin, dass die Worker-Threads beim Schließen meiner Anwendung ordnungsgemäß beendet werden, aber einer der beiden Unter-Haupt-Threads hängt (niemals beendet), wenn ich WM_QUIT zum Schließen ausstelle.

%Vor% %Vor%     
Atlas 23.10.2008, 13:05
quelle

3 Antworten

11

Wenn ich auf einige Probleme in Ihrem Code hinweisen könnte ...

1) Sie überprüfen nicht die Ausgabe von AllocateHwnd. Ja, wahrscheinlich wird es nie versagen, aber trotzdem ...

2) Zutreffende Belogs OUT of try..finally! Wenn dies fehlschlägt, sollte DeallocateHwnd nicht aufgerufen werden.

3) AllocateHwnd ist nicht threadsicher. Wenn Sie es von mehreren Threads gleichzeitig aufrufen, können Sie auf Probleme stoßen. Lesen Sie mehr.

Wie Davy sagte, verwenden Sie MsgWaitForMultipleObjects, anstatt ein verstecktes Nachrichtenfenster zu erstellen. Verwenden Sie anschließend PostThreadMessage, um Nachrichten an den Thread zu senden.

Wenn ich hier einen Stecker für ein völlig kostenloses Produkt einsetzen kann, verwende stattdessen meine OmniThreadLibrary . Viel einfacher als direkt mit Windows Messaging zu verwirren.

    
gabr 23.10.2008 17:10
quelle
9

Ich hatte das gleiche Problem, und ich fand heraus, dass nicht ein verstecktes Fenster erstellen sollte, um Nachrichten zu empfangen. Threads haben bereits ein Nachrichtensystem.

Ich denke, dass Sie Ihr Windows-Handle erstellen und es in fHandle speichern, aber GetMessage überprüft die Nachrichtenschleife des Threads. Daher die Nachricht PostMessage (fHandle, WM_QUIT, 0, 0); wird nie von der getmessssage empfangen.

Sie können Nachrichten mit PostThreadMessage in Ihren Thread schreiben, und im Thread verwenden Sie GetMessage (CurrentMessage, 0, 0, 0). Der einzige wichtige Unterschied besteht darin, dass Sie die Nachrichtenschleife aus Ihrem Thread starten müssen, indem Sie

aufrufen %Vor%

Sie sollten damit beginnen, als Ihre Einrichtung und dann Ihre Schleife starten.

Der Grund, warum Sie mit der Peek-Nachricht beginnen sollten, ist sicherzustellen, dass Nachrichten, die während der Initialisierung Ihres Thread-Prozesses gesendet werden, nicht verloren gehen.

Das Seltsame ist, dass ich im Moment nicht den Hinweis finde, wo ich das gelernt habe, aber ich schätze die Newsgroup-Community.

    
Davy Landman 23.10.2008 13:57
quelle
6

1) Sie brauchen nicht in AllocateHwnd innerhalb Ihres Threads. Der erste Aufruf von GetMessage erstellt eine separate Nachrichtenwarteschlange für diesen Thread. Um jedoch eine Nachricht an den Thread zu senden, sollten Sie die PostThreadMessage-Funktion verwenden.

Beachten Sie, dass zum Zeitpunkt des Aufrufs von PostThreadMessage die Warteschlange noch nicht erstellt werden konnte. Ich benutze normalerweise Konstruktion:

%Vor%

, um sicherzustellen, dass die Nachrichtenwarteschlange erstellt wurde.

2) Zum Beenden der Thread-Schleife definiere ich meine eigene Nachricht:

%Vor%

3) Es ist kein separates Ereignis erforderlich, da Sie Threadhandle übergeben können WaitForSingleObject-Funktion. So könnte Ihr Code wie folgt aussehen:

%Vor%

Berücksichtigen Sie, dass ThreadID und ThreadHandle unterschiedliche Werte sind.

4) So wird Ihr ThreadProc wie folgt aussehen:

%Vor%     
Andrei 23.10.2008 15:50
quelle

Tags und Links