Thread der endet aber nicht beendet ?



  • Und ich würde anstelle des int Killflags auch eine CEvent verwenden, um den Thread über wichtige Ereignisse zu informieren:

    UINT BenchMarkThread(LPVOID param)
    {
    //  threadcontrol.benchmarkstatus=true; // erübrigt sich, das Hauptprogramm kann auch auf das Thread-Ende mit Wait... warten
        while(WaitForSingleObject(threadcontrol.shutdown,0)==WAIT_TIMEOUT)
        {
            QueryPerformanceCounter(&benchmark.SP_PC_Start);
    
            Sleep(2000);
    
            double PSec_PC=double(benchmark.SP_PC_Stopp.QuadPart-benchmark.SP_PC_Start.QuadPart)/double(benchmark.PC_Freq.QuadPart);
        }
    //  threadcontrol.benchmarkstatus=false;
        return 1;
    }
    
    void foo()
    {
        threadcontrol.globalshutdown.SetEvent();
        WaitForSingleObject(threadcontrol.benchmarkThread->m_hThread,INFINITE);
        delete threadcontrol.benchmarkThread;
    }
    

    (damit letzteres zuverlässig funktioniert, mußt du (wie hustbaer schon angedeutet hat) das m_bAutoDelete Flag beim Thread-Start auf false setzen)



  • hustbaer schrieb:

    p.S.: wenn du AfxBeginThread verwendest bekommst du ein CWinThread Objekt zurück wo das m_bAutoDelete Member auf "true" gesetzt ist. Dadurch zerstört der Thread bevor er sich beendet das Objekt automatisch, und das Thread-Handle wird freigegeben. In dem Fall darf man WaitForSingleObject nicht verwenden, da das Handle ja freigegeben wird bevor der Thread terminiert, WaitForSingleObject allerdings erst zurückkehren würde nachdem der Thread terminiert hat, und man so effektiv WaitForSingleObject das Handle "unterm Hintern wegziehen" würde.
    Du kannst entweder _beginthreadex verwenden, oder, wenn du einen MFC Thread brauchst, CREATE_SUSPENDED mitgeben, das m_bAutoDelete Member auf "false" setzen, und den Thread dann erst mit ResumeThread starten.
    Beide Varianten funktionieren zuverlässig und sind gleichermassen "OK", die _beginthreadex finde ich persönlich allerdings wesentlich weniger umständlich

    Mal eine Frage dazu? Warum startest du den Thread erst mit CREATE_SUSPENDED, setzt dann m_bAutoDelete auf false und lässt ihn dann weiterlaufen? Ich hab das bisher immer so gemacht:

    CWindThread* m_pThread;
    m_pThread=AfxBeginThread(ThreadFunc,this,THREAD_PRIORITY_NORMAL);
    m_pThread->m_bAutoDelete=false;
    

    Könnte das Probleme geben? Bisher hat es ja immer funktioniert...

    @CStoll: was machst du denn mit dem Event im Thread? oder hast du da zu viel auskommentiert?


  • Mod

    Die Methode mit CREATE_SUSPENDED geht in Ordnung und funktioniert!



  • AndyDD schrieb:

    @CStoll: was machst du denn mit dem Event im Thread? oder hast du da zu viel auskommentiert?

    Drauf "warten" - sorry, hatte den Kopf der while-Schleife versehentlich auskommentiert. (WaitForSingleObject(...,0) kehrt sofort zurück - entweder mit WAIT_OBJECT0 (das Ziel ist signalisiert) oder mit WAIT_TIMEOUT)



  • AndyDD schrieb:

    Mal eine Frage dazu? Warum startest du den Thread erst mit CREATE_SUSPENDED, setzt dann m_bAutoDelete auf false und lässt ihn dann weiterlaufen? Ich hab das bisher immer so gemacht:

    CWindThread* m_pThread;
    m_pThread=AfxBeginThread(ThreadFunc,this,THREAD_PRIORITY_NORMAL);
    m_pThread->m_bAutoDelete=false;
    

    Könnte das Probleme geben?

    UINT ThreadFunc(void*)
    {
        printf("sepp\n");
    }
    
    void foo()
    {
        CWindThread* m_pThread;
        m_pThread=AfxBeginThread(ThreadFunc,this,THREAD_PRIORITY_NORMAL);
        // context switch, thread läuft, thread beendet sich
        m_pThread->m_bAutoDelete=false; // <- BOOM!
    }
    


  • Martin Richter schrieb:

    Die Methode mit CREATE_SUSPENDED geht in Ordnung und funktioniert!

    Das ist mir schon klar. Ich fragte nach dem Warum zu dieser Vorgehensweise.

    hustbaer schrieb:

    UINT ThreadFunc(void*)
    {
        printf("sepp\n");
    }
    
    void foo()
    {
        CWindThread* m_pThread;
        m_pThread=AfxBeginThread(ThreadFunc,this,THREAD_PRIORITY_NORMAL);
        // context switch, thread läuft, thread beendet sich
        m_pThread->m_bAutoDelete=false; // <- BOOM!
    }
    

    Ok, wenn die Threadfunktion returniert bevor man das AutoDelete auf false setzen konnte, dann seh ich das ein. Beide "Fäden" laufen ja quasi parallel. Aber wann tritt denn das auf? Lagert man nicht extra zeit- und prozessorlastraubende Dinge in einen solchen Workerthread aus? Dann dürfte der Thread ja immer länger leben als die Zugriffszeit aufs CWinThread-Objekt. Außerdem wird das von mir weiter oben gepostete Vorgehen auch in vielen Literaturstellen so angewendet. Klar, vertrauen kann man darauf nicht. Die von euch favorisierte Variante würde das abfangen.



  • Vielleicht hat der Thread ja eine andere Meinung davon, wie lange er benötigt als du - und nicht immer ist das so offensichtlich wie in diesem Beispiel 😉 Und sobald es ans Mutlithreading geht, mußt du jederzeit damit rechnen, daß Thread A (das Hauptprogramm) schlafen gelegt und Thread B (der Worker) an den Prozessor gelassen wird.


  • Mod

    AndyDD schrieb:

    Ok, wenn die Threadfunktion returniert bevor man das AutoDelete auf false setzen konnte, dann seh ich das ein. Beide "Fäden" laufen ja quasi parallel. Aber wann tritt denn das auf? Lagert man nicht extra zeit- und prozessorlastraubende Dinge in einen solchen Workerthread aus? Dann dürfte der Thread ja immer länger leben als die Zugriffszeit aufs CWinThread-Objekt. Außerdem wird das von mir weiter oben gepostete Vorgehen auch in vielen Literaturstellen so angewendet. Klar, vertrauen kann man darauf nicht. Die von euch favorisierte Variante würde das abfangen.

    1. Es tritt sehr schnell auf, wenn der Workerthread mit höherer Prio läuft und sofort loslegt und relativ schnell fertig wird, evtl. unerwartet weil eine Ressource nicht zur Verfügung steht.
    2. So etwas nicht zu berücksichtigen, bzw. auch nicht den Fall, dass AfxBeginThread NULL returniert sind nette Fehler, die einen beim Einsatz beim Kunden den letzten Nerv rauben können.
    3. Ich würde gerne Wissen welche Literaturquellen Du hier meinst? Ich würde diese Quellen sofort entsorgen, denn der Autor hat von Multithreading dann wirklich keine Ahnung.



  • Aber wann tritt denn das auf?

    Immer genau dann wenn es am meisten Schaden anrichten kann.


  • Mod

    hustbaer schrieb:

    Aber wann tritt denn das auf?

    Immer genau dann wenn es am meisten Schaden anrichten kann.

    Auch ein "Jünger des Murphy"! Findet man selten heute, die meisten Programmierer heute gehen den Weg der sinnlosen Hoffung: "Es wird schon immer alles gut gehen"

    😃


Anmelden zum Antworten