PostMessage() nach DestroyWindow(): Undefiniertes Verhalten?
-
1. Warum nutzt Du überhaupt SendMessage?
2. Könntest Du einfach bevor das Fenster geschlossen wird, dem Thread sagen das fini ist. Der Thread weiß dann, nun ist Schluß und er darf nix mehr senden und wird alsbald terminieren.
Dann blockiert auch nichts.
-
Weil ich mit SendMessage() vom Downloadthread das Fenster+Childs vom Hauptthread erreichen will.
Ja, es wird auch "abort = true;" gesetzt. Aber dann lauter Abfragen im Downloadthread "if(abort) ..." finde ich unschön.
-
1. Kannst Du eine Funktion in der Threadklasse schreiben, die NotifyThread heißt und dann hast Du nur eine Stelle mit SendMessage. Ich finde verteile SendMessage aufrufe in einem Thread unschön, schon ganz und gar wenn mehrere Fenster bedient werden...
2. Warum sendest Du nicht nur eine einzige Nachricht immer an das Hauptfenster und diese Nachricht wird dann an die Unterfenster verteilt.
3. Durch SendMessage erreicht man eine threadsynchronisation, warum also nicht PostMessage?
-
Also NotifyThread() soll ein PostMessage() mit IsWindow() Abfrage davor sein?
Wie, nur eine Nachricht? Es werden Nachrichten von verschiedenen Stellen gesendet.
Im Downloadthread, wenn ein URLDownloadToFile() fehlschlägt, werden Childs aktualisiert (static control: "Download failed").
Im Downloadthread, in IBindStatusCallback::OnProgress() wird eine Progress Bar upgedated.Ich gehe außerdem nicht davon aus, dass die message loop hängen bleibt, also brauche ich doch kein PostMessage()?
-
Für die Kommunikation eines Threads mit einem Fenster, sende ich nur eine Nachrichtenart (WM_APP+n), in den Argumenten w/lParam, sage gebe ich an was passiert.
Das Mainwindow ist verantwortlich für den Progressbar etc...
Apropos MessageLoop: Du hast doch genau jetzt das Problem. Deine Messageloop hört auf zu laufen und SendMessage blockiert

-
Ok und was ist der Vorteil, nur eine Nachricht zu senden?
Und ich habe es mehrfach getestet, SendMessage() blockiert nicht, wenn die message loop schon beendet ist.
-
Destroy0r schrieb:
Ok und was ist der Vorteil, nur eine Nachricht zu senden?
Und ich habe es mehrfach getestet, SendMessage() blockiert nicht, wenn die message loop schon beendet ist.
Aber nur wenn das Fenster nicht mehr existent ist!
Sonst muss es blockieren...
-
Naja, dass das Fenster noch existiert während die message loop schon beendet ist, kommt in meiner Anwendung nie vor. Oder wie könnte es dazu kommen?
WM_CLOSE -> DestroyWindow()
WM_DESTROY -> PostQuitMessage()Und wenn ich ja mit IsWindow() prüfen kann, sehe ich keinen Vorteil in einer einzigen WM_APP+n Nachricht. Dann müsste ich dafür außerdem eventuell noch extra Strukturen definieren...
Oder findest du es einfach schöner, wenn ein Thread nur an das Hauptfenster, nicht aber an die Childs sendet?
-
@hustbaer
Ja, und wenn ich es doch tue? UB? Oder wird es intern einfach ignoriert?Wieso interessiert dich das? Schreib dein Programm so, dass der Fall nicht vorkommt.
@Martin:
IsWindow() ist sinnlos, dann kann er genauso gleich die Message absetzen. Wenn das Handle nicht schon neu vergeben wurde, dann geht die Message ins nirvana, und es passiert einfach nix. Bzw. wird die Message nichtmal abgeschickt.
Und WENN das Handle schon neu vergeben wurde, dann wird IsWindow() auch true melden, obwohl es schon ein ganz anderes Fenster gibt.IsWindow() ist IMO nur für ASSERTs brauchbar.
-
Weil ich dann im Downloadthread ne zusätzliche Abfrage brauche. Und da ich jetzt IsWindow() nicht verwenden soll, wohl irgendwie so:
bool _abort; EnterCriticalSection(&criticalSectionAbort); _abort = abort; LeaveCriticalSection(&criticalSectionAbort); if(!_abort) PostMessage(dialogHandle, WM_CLOSE, 0, 0);Aber gibt es nun kein UB?
-
@Destroy0r: Deine CriticalSection ist absolut unnötig.
Bei Deinem Konstrukt stellt sich für mich einfach die Frage,warum ein zerstören des Hauptfensters überhaupt erlaubt ist, während der Download läuft.@hustbaer: Window Handles werden nicht "schnell" recycled. Das ist so weit erstmal sicher. Es gibt aber genug Race-Konditions in denen man z.B. in PreTranslateMessage, oder einem Hook etwas auslöst, was zum Beispiel andere Fenster zerstört. In diesem Moment kommt IsWindow schon zum tragen.
Was SendMessage angeht, gebe ich Dir recht, allerdings gibt IMHO im Aplication Verifier einen Break, wenn ein Handle verwendet wird, das nciht existiert!
Durch ein Certified for xyz würde die Anwendung dann durchfallen.
-
Ne, die ist nicht unnötig, weil "abort" im Hauptthread auf "true" gesetzt wird, und zwar bevor dort DestroyWindow() aufgerufen wird.
Und sobald eine Variable in zwei Threads verwendet wird, muss doch synchronisiert werden.Und ich möchte dem User die Kontrolle lassen, wann er den Updater abbrechen will. Wenn ein Download läuft, muss der User bestimmt nicht warten, bis dieser fertig ist.
Er wird dann zwar durch IBinding::Abort() abgebrochen, aber es könnte Folgendes passieren:if(!abort) { UrlDownloadToFile(... ...Wenn abort noch false ist, und genau danach das Fenster geschlossen wird, während also erstmal UrlDownloadToFile() beginnt, darf man noch nicht IBinding::Abort() aufrufen.
Und wenn der Server dann hängt, hängt die Applikation.Deshalb werde ich wohl libcurl mit dem multiinterface verwenden, da kann immer kontrolliert abgebrochen werden.
-
Destroy0r schrieb:
Ne, die ist nicht unnötig, weil "abort" im Hauptthread auf "true" gesetzt wird, und zwar bevor dort DestroyWindow() aufgerufen wird.
Und sobald eine Variable in zwei Threads verwendet wird, muss doch synchronisiert werden.nö es ist eine atomare operation
-
@hustbaer: Window Handles werden nicht "schnell" recycled.
Das weiss ich schon.
Das ist so weit erstmal sicher.
Sicher nenne ich was anderes. Sagen wir lieber es macht die Sache weniger schlimm.
Es gibt aber genug Race-Konditions in denen man z.B. in PreTranslateMessage, oder einem Hook etwas auslöst, was zum Beispiel andere Fenster zerstört. In diesem Moment kommt IsWindow schon zum tragen.
Jo. Deswegen ist IMO das ganze Window-Gedöns in Windows ja auch ein riesen Haufen Müll.
Was SendMessage angeht, gebe ich Dir recht, allerdings gibt IMHO im Aplication Verifier einen Break, wenn ein Handle verwendet wird, das nciht existiert!
Durch ein Certified for xyz würde die Anwendung dann durchfallen.Mag sein, ich hab noch nie eine Anwendung verifizieren lassen. Ist aber total bescheuert, weil wie gesagt das nötige "if" ja schon in SendMessage steckt.
-
@atomb0mb3
Wie jetzt, ich muss nicht synchronisieren? Oh mann, jeder sagt was anderes. Schöne Scheisse! Wie soll man es dann richtig lernen...
-
Destroy0r schrieb:
@atomb0mb3
Wie jetzt, ich muss nicht synchronisieren? Oh mann, jeder sagt was anderes. Schöne Scheisse! Wie soll man es dann richtig lernen...du solltest es mit InterlockedExchange machen.
-
Also was nun, Synchronisation nötig oder nicht

-
atomb0mb3 schrieb:
Destroy0r schrieb:
Ne, die ist nicht unnötig, weil "abort" im Hauptthread auf "true" gesetzt wird, und zwar bevor dort DestroyWindow() aufgerufen wird.
Und sobald eine Variable in zwei Threads verwendet wird, muss doch synchronisiert werden.nö es ist eine atomare operation
Nicht auf jeder CPU, und nicht jede Variable.
Und generell auch nur, wenn das Alignment passt, was wiederum nicht jeder Compiler garantieren muss.Mal ganz davon abgesehen dass der C++ Standard diesbezüglich garkeine Garantien abgibt, weil er (noch) kein Speichermodell vorschreibt, und keine Threads kennt.
-
Alles klar, dann synchronisiere ich.
Soll ich dann InterlockedExchange() für eine reine Abfrage so verwenden?if(InterlockedExchange(&abort, abort)) ...
-
ist nicht notwendig, wie martin richter schon sagte