Probleme mit Threads



  • Hi Leute,

    so hab leider gerade ein paar Probleme mit einem Thread. Der Thread wird gestartet und soll wieder beendet werden.

    Was ist das Problem?
    Das Problem ist, wenn ich in dem Standard-Thread die m_bInitUpdateThreadShudown Variable auf TRUE setzen, um die While-schleife zu unterbrechen, bleibt diese konstant -> wird nicht beendet?

    Sieht jemand ein Problem?

    Def:

    static DWORD WINAPI UpdateThread( LPVOID lpParam );
    	int CreateUpdateThread();
    	int TerminateUpdateThread();
    

    Inits (Konstruktor)

    m_bInitUpdateThreadShutdown	= FALSE;
    	m_bUpdateThreadRunning		= FALSE;
    
    DWORD WINAPI CManager::UpdateThread( LPVOID lpParam )
    {
    
    	CManager *pManager = (CManager*)lpParam;
    	pManager->m_bUpdateThreadRunning = TRUE;
    
    	// while running start update (ist zuerst auf FALSE bis sie beim beenden auf true gesetzt wird
    	while( pManager->m_bInitUpdateThreadShutdown == FALSE )
    	{
    		// tue was
    	}
    
    	// set running falue to false
    	pManager->m_bUpdateThreadRunning = FALSE;
    	return 1;
    }
    

    So hier wird der Thread erstellt.

    if( m_hUpdateThread == NULL )
    	{
    		m_hUpdateThread = CreateThread( NULL, 
    						0, 
    						CManager::UpdateThread, 
    						(LPVOID)this, 
    						0, 
    						0 );
    		// setup running var
    		if( m_hUpdateThread )
    		{
                            //success
    			return 1;
    		}
    	}
    


  • Sind die Member von CManager

    bool m_bInitUpdateThreadShutdown;
    bool m_bUpdateThreadRunning;
    

    oder

    static bool m_bInitUpdateThreadShutdown;
    static bool m_bUpdateThreadRunning;
    

    Gruss, Gio



  • Erstmal muss ich sagen dass das OP ein sehr schönes Codefragment ist; sprechend benannt und gut ziziert usw.

    Das sieht eignetlich alles blitzsauber aus; ich glaub zwar nicht dass es um die Flags zu "Racing" kommt, aber wieviele weitere Zyklen hast Du denn gezählt ( >2 ?) ? Testausschrift oder Debugger?

    Du hast nicht zufällig nur ein "=" zuviel und schreibst statt

    m_bInitUpdateThreadShutdown = TRUE;
    
    m_bInitUpdateThreadShutdown == TRUE;
    

    ?

    Sonst fällt mir da gar nichts Verdächtiges auf; ganz im Gegenteil!

    Grüsse

    *this



  • Hi,

    Also ich habe die Variablen ohne Static initiiert -> Das müssten sich auch nicht (bitte korrigiert mich, wenn was falsch ist).

    Das habe ich zuerst auch gedacht, dass evt. eine Vergleichsoperation mit einer Übergabe Operation verdauscht wurde. Dem ist jedoch nicht so.
    Alles sollte seine Richtigkeit haben - bin momentan etwas aufgeschmissen probiere jetzt seit ein paar Tagen.

    An dieser Stelle ein großes Danke für die schnelle Antwort! Falls jemand nochwas dazu einfällt könnte das hier mal posten! 🙄



  • Wie und wo setzt der "Standard-Thread" Member "m_bInitUpdateThreadShutdown" auf TRUE ?
    Eventuell ist der übergebene this-pointer dort nicht mehr gültig ?



  • Also ich warte, bis mein Dialog ein Signal erhält (Button!). Ich greife über eine static CBaseApp *pBasApp; Variable auf die Basis klasse zu und rufe "Release" auf.

    Das Klappt wunderbar, erhalte schöne Nacrichten! 🙂

    //------------------------------------------------------------------
    int CTableManager::TerminateUpdateThread()
    {
    	if( m_bUpdateThreadRunning )
    	{
    		//::TerminateThread( this->m_hUpdateThread, 0 );
    		this->m_bInitUpdateThreadShutdown = TRUE;
    		while( m_bUpdateThreadRunning )
    		{
                          // warte bis der Thread beendet ist (das kommt nicht zm Ende)
    		}//while
    	}
    }
    


  • JayJay schrieb:

    //------------------------------------------------------------------
    int CTableManager::TerminateUpdateThread()
    {
    	if( m_bUpdateThreadRunning )
    	{
    		//::TerminateThread( this->m_hUpdateThread, 0 );
    		this->m_bInitUpdateThreadShutdown = TRUE;
    		while( m_bUpdateThreadRunning )
    		{
                          // warte bis der Thread beendet ist (das kommt nicht zm Ende) (*)
    		}//while
    	}
    }
    

    Bei (*) ist doch wohl ein Sleep oder sowas drin? Sonst wär der Hauptthread ein wenig zu dominant um dem UpdateThread Zeit für's toggling geben. 🙂

    Btw. ist dieser Threadmanager ein Singleton oder wird zumindest so benuztzt?
    Bau doch mal einen statischen Counter in die Manager-Klasse ein (Alle ctors : ++counter_/dtor --counter_, Copy-ctor sollte definiert sein); wenn Du die Instanzvariable eines anderen Manager setzt hat der Thread natürlich keine Chance das mitzukriegen; er kennt ja nur die Instanz die er sich aus dem Thread-Parameter gecastet hat!

    Vielleicht wird da irgendwo implizit kopiert?

    Grüsse

    *this



  • Gast++ schrieb:

    JayJay schrieb:

    while( m_bUpdateThreadRunning )
    		{
                          // warte bis der Thread beendet ist (das kommt nicht zm Ende) (*)
    		}//while
    

    Bei (*) ist doch wohl ein Sleep oder sowas drin? Sonst wär der Hauptthread ein wenig zu dominant um dem UpdateThread Zeit für's toggling geben. 🙂

    ich würde das nicht mit solchen bool-variablen hinfrickeln. dafür gibt's doch schicke APIs --> http://msdn2.microsoft.com/en-us/library/ms687032.aspx



  • Prüfe auch mal wie Gast++ vorschlagen hat, ob "static CBaseApp *pBasApp;" eventuell überschrieben, bzw. mehrmals initialisiert wird.

    Vielleicht liegt folgendes Problem vor :

    //-----------------------------------------------------
    //-----------------------------------------------------
    int CTableManager::TerminateUpdateThread()
    {
    ...
     if( m_bUpdateThreadRunning )
     {
    ...
      this->m_bInitUpdateThreadShutdown = TRUE; // <- dieser this-pointer ist...
    ...
     }
    
    }
    //-----------------------------------------------------
    //-----------------------------------------------------
    if( m_hUpdateThread == NULL )
    {
      m_hUpdateThread = CreateThread( NULL, 
                        0, 
                        CManager::UpdateThread, 
                        (LPVOID)this,           // <- ungleich jenem
                        0, 
                        0 );
    ...
    }
    


  • So hab einen Sleep(50); reingemacht und klappt soweit wunderbar.

    Hat jemand Ideen, wie ich evt. Synchronisationen ohne bool variablen organisieren kann? gibt es generelle Einwände?



  • JayJay schrieb:

    So hab einen Sleep(50); reingemacht und klappt soweit wunderbar.

    Hat jemand Ideen, wie ich evt. Synchronisationen ohne bool variablen organisieren kann? gibt es generelle Einwände?

    Events

    http://www.codeproject.com/win32/Win32_Event_Handling.asp

    sind eine Möglichkeit; was genau willst Du denn machen?

    Grüsse

    *this



  • Deine "while (m_bUpdateThreadRunning) {}" Schleife kommt deswegen ohne Sleep() nicht zu einem Ende, weil der Zugriff auf m_bUpdateThreadRunning wegoptimiert wurde. Rufst du dagegen eine Systemfunktion wie Sleep in der Schleife auf kann der Compiler den Zugriff nichtmehr wegoptimieren, und es funktioniert.

    Der eigentliche Fehler ist nicht dass Sleep nicht aufgerufen wurde, sondern dass ohne Synchronisation von 2 Threads auf eine Variable zugegriffen wird.

    In so einem Fall sollte man critical sections verwenden, oder ne Mutex, oder eben nen Event an Stelle der Variable.
    Und warten bis der Thread terminiert kann man einfach indem man auf das Thread Handle wartet.


Anmelden zum Antworten