In meiner C ++ - Anwendung habe ich einen Hintergrund-Thread, der etwas Arbeit leistet, indem er die Ergebnisse in einen Heap-allokierten Speicherblock schreibt und PostMessage , um die Ergebnisse an den Haupt-Thread zu übermitteln.
Wenn das Window die Nachricht empfängt, verarbeitet es normalerweise die Ergebnisse und führt dann delete
für den von lParam
angegebenen Speicher aus.
Aber ich bin besorgt, dass das Fenster möglicherweise beendet wird, bevor es die Nachricht verarbeitet und den Speicher löscht.
Gewährleistet PostMessage
irgendwie, dass das Zielfenster eine Chance bekommt, die Nachricht zu verarbeiten?
Wenn nicht, gibt es eine wohlbekannte Technik, um zu wissen, ob das Fenster den Speicher freigegeben hat oder ob der Hintergrund-Thread dafür verantwortlich sein muss, es zu löschen?
PostMessage
wird definitiv in die Nachrichtenwarteschlange des Empfangsfensters gestellt. Es gibt jedoch keine Garantie, dass das Fenster vorhanden ist. Es könnte zu dieser Zeit zerstört worden sein.
Eine Möglichkeit, die Nachricht zu sichern, besteht darin, ein eigenes, verstecktes Fenster zu erstellen (COM verwendet diese Technik häufig) und es in seine Warteschlange zu stellen. Auf diese Weise haben Sie die Kontrolle darüber, wann das versteckte Fenster zerstört wird. Wir haben diese Methode seit vielen Jahren in Echtzeit-Datenlieferung eingesetzt.
Wenn der Hintergrund-Thread den Speicher löscht, ist das eine schlechte Idee und kann zu einem Race-Zustand führen, bei dem er nicht weiß, wann er gelöscht werden kann. Es ist besser, in das eigene Fenster zu schreiben und es dort zu löschen, wenn Sie damit fertig sind.
Betrachten Sie die klassische Nachrichtenschleife eines UI-Threads:
%Vor%Ihre Nachricht, die von dem anderen Thread gepostet wird, wird abgerufen und versendet, aber ihre Lieferung hängt davon ab, ob das Zielfenster erfolgreich erstellt wurde (und noch nicht zerstört wurde). Sie könnten die Nachricht direkt in der Nachrichtenschleife behandeln, wenn Sie die Kontrolle darüber haben. Es kann jedoch kompliziert werden, wenn eine andere (verschachtelte) Nachrichtenschleife vorhanden ist, die als Ergebnis der Behandlung einiger Windows-Nachrichten erstellt werden kann. Ein einfaches Beispiel hierfür ist ein modaler Dialog, aber komplexere Dinge wie COM-Call-Outs können auch verschachtelte Nachrichtenschleifen enthalten.
Sie sollten sich also nicht auf die garantierte Nachrichtenzustellung verlassen. Erwägen Sie die Verwendung einer globalen Datenstruktur wie Warteschlange oder Liste (geschützt vor gleichzeitigem Zugriff mit einem kritischen Abschnitt), um Ihre Datenobjekte in eine Warteschlange zu stellen. Dann können Sie noch eine Nachricht mit PostMessage
posten und einen Zeiger auf Ihr Datenobjekt in lParam
übergeben, aber in Ihrem Message-Handler müssten Sie das Objekt in der globalen Warteschlange suchen und die Objekte verarbeiten (oder verwerfen) wurden früher in die Warteschlange gestellt, aber aus irgendeinem Grund nicht verarbeitet. Im Allgemeinen, wenn Ihr Thread beendet wird ( WM_QUIT
Nachricht kam in der obigen Schleife an), sollten Sie einige Bearbeitungen an dem durchführen, was auch in der Warteschlange übrig war.