PostMessage() nach DestroyWindow(): Undefiniertes Verhalten?


  • Mod

    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?


  • Mod

    @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



  • @PullePepe
    Du meinst damit jetzt die Abfrage auf ein totes Fenster?



  • Destroy0r schrieb:

    @PullePepe
    Du meinst damit jetzt die Abfrage auf ein totes Fenster?

    Nein, der Aufruf von InterlockedExchange oder EnterCriticalSection. Das brauchst du nur bei Anwendungen, die speziell auf Mehrprozessorsysteme zugeschnitten sind.


  • Mod

    Für rein Flag vom Typ bool oder Integer ist höchstens das Keywort volatile notwendig. Weder InterlockExchange noch CriticalSection. Warum auch?


  • Mod

    hustbaer schrieb:

    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.

    Nein tut es nicht. Wenn z.B. Hooks installiert werden oder OLE läuft (STA läuft über die Message Queue) dann greifen intern Mechanismen, die es z.T. nicht mögen, dass Nachrichten an Fenster gesandt werden, die 1. Nicht existieren oder 2. nicht mehr existieren.



  • Höchstens volatile. Und wann?
    Ich dachte, man muss einen Zugriff aus mehreren Threads synchronisieren.
    So wie ich @hustbaer verstanden habe, sollte ich synchronisieren.


  • Mod

    hustbaer hat nichts dergleichen gesagt...

    Du hast ein Flag abort. Das soll geprüft werden...
    Wenn es gesetzt ist Abbruch, wenn nicht ein neuer Schleifendurchlauf?
    Was soll hier eine Schutz der Variable?
    Was denkst Du denn was anders wird?

    CriticalSection müssen verwendet werden wenn Wertepaare/gruppen maipuliert werden.

    volatile sagt dem Compiler, dass diese Variable, von extern (anderer Thread) geändert werden kann. Der Compiler darf also diese Variable nicht optimieren.


Anmelden zum Antworten