File Handle innerhalb eines Threads bei SuspendThread() schließen



  • Tag zusammen.

    In meinem Projekt habe ich unter Umständen mehrere Threads laufen, die jeweils in eine Datei schreiben. Der Benutzer soll diesen Thread jetzt mittels Context Menü abbrechen können. Die Threads starte ich mit AfxBeginThread und den CWinThread Pointer speichere ich in einer Member Variable. Momentan stoppe ich den Thread mittels pThread->SuspendThread(). Was zwar zur Folge hat, dass nicht mehr in die Datei geschrieben wird, jedoch ist die Datei danach noch immer geöffnet, d.h. sie kann im Windows Explorer nicht gelöscht werden oder ähnliches.
    Die ofstream Variable wird dabei in der Threadfunktion selbst angelegt.
    Wie kann ich bewirken, dass die Datei bei SuspendThread() wieder freigegeben wird?
    Gibt es eventuell noch eine andere Funktion?

    Danke im Voraus!



  • SuspendThread solltest du nicht verwenden, steht auch schon in der MSDN so geschrieben.
    Bring deinem Thread bei auf irgendein Signal zu reagieren und sich daraufhin kontrolliert selbst zu beenden. Dabei kann der Thread dann das Handle selbst freigeben.
    Alles andere (SuspendThread, TerminateThread) ist Murks.



  • Vielen Dank für deine Hilfe. Was gibt es denn für geeignete Möglichkeiten um das zu realisieren? Ich könnte ja ständig den Wert einer BOOL Variable überprüfen und wenn diese einen bestimmten Wert hat den Thread beenden usw. aber ich denke nicht, dass das eine optimale und saubere Lösung ist. Kann mir jemand vielleicht ein konkretes Beispiel geben?

    Danke!



  • Guck dir mal Events an, die sind oft recht nützlich. Kannst du mit CreateEvent erstellen und mit WaitForSingleObject darauf warten. Damit musst du auch kein "busy waiting" machen, falls du auf einen bestimmten Zustand wartest, mit WAIT_TIMEOUT == WaitForSingleObject(ev,0) kannst du auch zwischendurch prüfen, ob das Handle gesetzt ist. Dazu gibts noch SetEvent und ResetEvent.
    Ach, sieht nach MFC aus, dann schau dir einfach mal die Klasse "CEvent" an



  • Vielen Dank Badestrand, werd ich mir morgen mal genauer ansehen das Ganze.
    Und ja, ich verwende MFC, hast richtig erkannt.



  • Dieser Thread wurde von Moderator/in HumeSikkins aus dem Forum C++ in das Forum MFC (Visual C++) verschoben.

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

    Dieses Posting wurde automatisch erzeugt.



  • frozen-one schrieb:

    Vielen Dank für deine Hilfe. Was gibt es denn für geeignete Möglichkeiten um das zu realisieren? Ich könnte ja ständig den Wert einer BOOL Variable überprüfen und wenn diese einen bestimmten Wert hat den Thread beenden usw. aber ich denke nicht, dass das eine optimale und saubere Lösung ist. Kann mir jemand vielleicht ein konkretes Beispiel geben?

    Danke!

    Was du da beschreibst kenne ich unter dem Begriff "kill flag", und das ist oft die beste Lösung. Ganz einfach weil sie einfach ist und funktioniert. Gerade wenn der Worker-Thread IO macht kann man sich sowieso nicht aussuchen wann man die Checks ob man abbrechen sollte durchführt, und da ist Polling mit einem Flag oft genausogut wie irgendwelche "Event Variablen" o.ä.

    Das einzige was man IMO immer machen sollte ist dieses "kill flag" über eine Mutex zu schützen.

    Siehe auch hier:
    http://www.c-plusplus.net/forum/viewtopic-var-p-is-1425808.html#1425808

    Wenn natürlich sowieso schon irgendwie mit dem Thread kommuniziert wird kann man das "kill flag" einfach als zusätzliche Variable einführen, z.B. so (schematisch):

    Mutex g_mutex;
    Queue g_queue;
    Event g_event;
    bool g_killFlag;
    
    void MyThreadFunction()
    {
        for (;;)
        {
            ::WaitForSingleObject(g_event.GetHandle(), INFINITE);
            ::ResetEvent(g_event.GetHandle());
            ScopedLock l(g_mutex);
            while (g_queue.NotEmpty())
                ProcessQueueEntry(q_queue.Pop());
            if (g_killFlag)
                break;
        }
    }
    
    void SignalEnd()
    {
        ScopedLock l(g_mutex);
        g_killFlag = true;
        ::SetEvent(g_event.GetHandle());
    }
    

Anmelden zum Antworten