Mögliche Datenkorruption bei Beenden während gespeichert wird...



  • Hey!

    Folgendes interessiert mich sehr:
    Nehmen wir an, ich erstelle einen Thread (Neben dem Hauptthread, den man ja nicht selbst erstellen muss) und lasse dort Daten in eine Datei speichern.
    Nun klickt der Benutzer aber im Moment der Speicherung auf "X" und das Programm beendet. Wird nun der Thread sofort terminiert und die Datei ist korrupt, also die Speicherung nicht zu ende geführt worden?
    Wie verhindere ich das bei _beginthread() oder CreateThread()? Bitte für beide Funktionen Tipps geben.

    (Es handelt sich um eine Windows-Anwendung, daher läuft die Nachrichtenschleife u.a. für das beendende "X" in einem separaten Thread, daher bin ich mir ziemlich sicher, dass ich da eine Wartefunktion einbauen muss)

    Danke!
    MfG



  • Dann mache das doch mit der Warte-Funktion!
    Im übrigen, beginthread verwendet CreateThread, um Windows zu sagen, dass ein Threadobjekt zu erstellen ist. Also von daher, kann schonmal und existiert auch nur ein kleiner Unterschied, Stichwort CRT bei beginthread.

    Erstelle doch eine globale Variable (meinetwegen bDontExit) und vor dem Thread-Start setzt du diese auf true, wenn dann der User das Programm beenden will und bDontExit auf true steht, startest du einem Timer, der alle x Millisekunden überprüft, ob bDontExit auf false steht und wenn ja, das Programm schließt. Wenn der Nebenthread mit den Dateien fertig ist und das Programm ansich geschloßen werden kann, setzt du die Variable auf false und das Programm wird beendet.



  • Hm ok aber es ist doch so einfacher:

    if(threadHandle)
    		WaitForSingleObject(threadHandle, 10000);
    
    	PostQuitMessage(0);
    

    Aber was ist, wenn die Abfrage zwar TRUE ist, dann aber zum anderen Thread gewechselt wird, dieser fertig wird und dann WaitForSingleObject() für einen Thread aufgerufen wird, der nicht mehr existiert? Laut MSDN undefiniertes Verhalten.

    Muss ich mich da jetzt in verschiedensten Thread-Techniken einlernen, oder geht das einfacher/sicherer?

    Und wie ist das eigentlich mit WaitForSingleObject(), wird da aufgehört zu warten, wenn der Zielthread returned?

    Danke!
    MfG



  • ceplusplus@loggedoff schrieb:

    Nun klickt der Benutzer aber im Moment der Speicherung auf "X" und das Programm beendet. Wird nun der Thread sofort terminiert und die Datei ist korrupt, also die Speicherung nicht zu ende geführt worden?

    Wir sind hier zum Glück nicht im Winapi-Forum (wo deine Frage hingehört hätte), deshalb darf ich auch mal halbwissend herumdilettieren: Das Klick auf das X führt dazu, dass der Prozess eine Nachricht empfängt, die ihn dazu auffordert, sich zu beenden. Ob und wie er das tut -- vorzugsweise in einer Form, die keine Daten korrumpiert, ist ihm überlassen. Das OS schießt nicht einfach so Threads ab.



  • Kannst ja einen eigenen Signal-Handler schreiben. Das schlimmste was passieren könnte ist das dein Programm zu lange braucht dann und Windows die altbekannte "Programm reagiert nicht"-Meldung wirft und der Prozess dann vom User abgeschossen wird.



  • Dieser Thread wurde von Moderator/in HumeSikkins aus dem Forum C++ in das Forum WinAPI verschoben.

    Im Zweifelsfall bitte auch folgende Hinweise beachten:
    C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?

    Dieses Posting wurde automatisch erzeugt.


  • Mod

    ceplusplus@loggedoff schrieb:

    Hm ok aber es ist doch so einfacher:

    if(threadHandle)
    		WaitForSingleObject(threadHandle, 10000);
    
    	PostQuitMessage(0);
    

    Aber was ist, wenn die Abfrage zwar TRUE ist, dann aber zum anderen Thread gewechselt wird, dieser fertig wird und dann WaitForSingleObject() für einen Thread aufgerufen wird, der nicht mehr existiert? Laut MSDN undefiniertes Verhalten.

    Solange Du ein gültiges Handle hast, (CloseHandle nicht aufgerufen) kannst Du immer wieder das Handle benutzen. Also auch für WaitForSingleObject.

    Du solltestin solch einem Fall immer WaitForSingleObject(threadHandle, INFINITE); Es könnte ja sein, dass es länger als 10 Sekunden dauert.



  • Ok danke, in meinem Fall dauert das Speichern immer unter einer Sekunde, also lass ich das timeout bei 5000.

    Danke danke,
    MfG


  • Mod

    ceplusplus@loggedoff schrieb:

    Ok danke, in meinem Fall dauert das Speichern immer unter einer Sekunde, also lass ich das timeout bei 5000.

    Danke danke,
    MfG

    Das ist Quark. Warte einfach bis der Thread terminiert! Warum willst Du ein Timeout? Setze INFINITE!
    Es kann sehr wohl länger dauern als 5 Sekunden, wenn z.B. ein Shutdown erfolgt und auf einmal alle Programm schreiben wollen!



  • Ok daran habe ich nicht gedacht! Wenn ich nun drüber nachdenke, ist INFINITE eh besser, denn wenn der Thread nicht beendet, stimmt ja was nicht.
    Danke dir!

    MfG



  • BTW: wenn du _beginthread() verwendest, dann wird das Handle ungültig sobald der Thread terminiert (bzw. genaugenommen: kurz vorher). WaitForSingleObject mit einem Handle welches von _beginthread() gekommen ist ist daher immer ein Fehler!
    Verhindern tust du das indem du entweder CreateThread oder gleich (besser) _begintrheadex verwendest - die beiden Funktionen lassen das Handle nämlich leben solange bis du es selbst schliesst.

    Und ob du einfach in der WindowProc (bzw. im OnClose Handler) auf den Speicher-Thread warten kannst hängt davon ab ob der Speicher-Thread davon abhängig ist dass der Haupt-Thread noch Nachrichten verarbeitet. Wenn der Speicher-Thread Funktionen wie SendMessage verwendet ist davon auszugehen dass er den Haupt-Thread braucht. In dem Fall musst du WM_CLOSE anders implementieren, z.B. indem du falls der Speicher-Thread noch lebt sämtliche Child-Fenster disablest, und dann einen "close timer" setzt.
    In dem "close timer" kannst du dann pollen ob der Speicher-Thread schon fertig ist, und sobald er es ist dann z.B. einfach nochmal selbst ein WM_CLOSE posten.


Log in to reply