critical section problem



  • Hallo Leute,

    ich hab ein kleine prograämchen mit 2 threads welceh beide auf den gleichen comport zugreifen können.. eine thread ist ein timer, d.h. er liest zyklisch daten vom comport, und der andere schreib auf knopfdruck daten auf dem comport. Damit nich beide gleichzeit schreiben bzw. lesen können hab ich das mit cirtiacal section syncronisiert.

    Ab un zu hängt sich aber das programm auf. Habe rausgefunden, das Thread A in der Critical Section ist, und Thread B auch in die cirtical section will (enterCrictical section). Aber genau bei dieser methode bleibt das progamm hängen. Dürft doch nich passieren?

    Er wartet doch bei

    EnterCriticalSection (& _critSection)
    

    bis der andere thread

    LeaveCriticalSection (& _critSection)
    

    passiert hat oder?

    Hab ne dafür ne Mutex klasse geschrieben:

    class Mutex{
    
    	CRITICAL_SECTION _critSection;
    
    public:
    
    	//Konstruktor
    	Mutex () { InitializeCriticalSection (& _critSection); }
        //Destruktor
    	~Mutex () { DeleteCriticalSection (& _critSection); }
    
    	//Lock
    	void Acquire (UINT i=0){ TRACE("Before Lock %i\n",i); EnterCriticalSection (& _critSection); TRACE("Lock %i\n",i); }
    	//Unlock
        void Release (UINT i=0){ LeaveCriticalSection (& _critSection);TRACE("UnLock %i\n",i);  }
    
    };
    

    EDIT: Wenn er in critical section A geht, sende ich darin noch eine message

    ::SendMessage(m_hWnd,WM_PR2_DATASTATE,(WPARAM)it->c_str(),NULL);
    

    an
    an das fenster in dem ich auch den knopf drücke für datenübertragen..

    gibt es probleme mit dem messagehandler?

    wenn ich es mit PostMEssage mache schein es zu klappen?



  • BorisDieKlinge schrieb:

    gibt es probleme mit dem messagehandler?

    Soll das ein Ratespiel sein? Woher sollen wir wissen, was dein Messagehandler macht.

    PS: Schau dir mal RAII an, ist besser für Mutexes (oder wie ist die Mehrzahl).



  • Zeig mal lieber die Stelle, wo der Mutex benutzt wird.



  • Forum WinAPI wäre korrekt.



  • hallo leute, ich hab nochmal bischzen alles durchdebuggt, und bin auf

    folgenes gestoßen:

    Thread A durchläuft zyklisch folgenden Code und führt eine Message im Fenster X aus:

    m_Mutes.Acquire ();
    ::SendMessage(m_hWnd,WM_PR2_DATASTATE,(WPARAM)it->c_str(),NULL); //Hier hängt er sich auf
    m_Mutex.Release();
    

    Zur gleichen Zeit drück ich ein Button im Fenster X, welcher ein
    Messageevent OnClick aufruft in dem ich dieses tu:

    void CThreadTest::OnBnClickedTransfer()
    {
    m_Mutes.Acquire ();
    ...
    m_Mutex.Release();
    

    }
    d.h. Während er noch die Message der Thread A bearbeitet (welche in Fenster X implementiert ist), drück ich einen Button (welcher in Fenster X sitzt) welcher auch eine Message auslöst.. bumm...



  • Du hast einen Deadlock erkannt, nun behebe ihn.



  • BorisDieKlinge schrieb:

    hallo leute, ich hab nochmal bischzen alles durchdebuggt, und bin auf

    folgenes gestoßen:

    Thread A durchläuft zyklisch folgenden Code und führt eine Message im Fenster X aus:

    m_Mutes.Acquire ();
    ::SendMessage(m_hWnd,WM_PR2_DATASTATE,(WPARAM)it->c_str(),NULL); //Hier hängt er sich auf
    m_Mutex.Release();
    

    Zur gleichen Zeit drück ich ein Button im Fenster X, welcher ein
    Messageevent OnClick aufruft in dem ich dieses tu:

    void CThreadTest::OnBnClickedTransfer()
    {
    m_Mutes.Acquire ();
    ...
    m_Mutex.Release();
    

    }
    d.h. Während er noch die Message der Thread A bearbeitet (welche in Fenster X implementiert ist), drück ich einen Button (welcher in Fenster X sitzt) welcher auch eine Message auslöst.. bumm...

    Messages von einem anderen Thread and den UI Thread musst du mit PostMessage verschicken. SendMessage ist blockierend und damit hast du wie "Sehr schön" richtig erkannt hat einen Deadlock.

    Edit: Wobei das auch nicht immer hilft. Ich verschiebe den Thread mal nach WinAPI 😉
    Edit2: eventuell hilft auch SendMessageAsync ^^
    BR
    Vinzenz



  • Dieser Thread wurde von Moderator/in evilissimo 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.



  • @evilissimo: danke, so ein deadlock zu erkennen ist gar net so einfach;) ich schau mir mal SendMessageAsync an;)

    thx jungs



  • BorisDieKlinge schrieb:

    Hab ne dafür ne Mutex klasse geschrieben:

    wieso schreibt jemand eine klasse für 3 einfach zu verwendende funktionen?
    🙂



  • fricky schrieb:

    BorisDieKlinge schrieb:

    Hab ne dafür ne Mutex klasse geschrieben:

    wieso schreibt jemand eine klasse für 3 einfach zu verwendende funktionen?
    🙂

    weil die leute dank des c++ marketing wahns (und durch die teils diletantischen buchempfehlungen von mitgliedern hiesigen forums) den eindruck gewonnen haben, sie müssten alles, aber auch alles, in klassen stopfen, weil ihr code dann modularer und besser sei, etc. typisch c++'ler halt, machens sich immer komplizierter als nötig :lol:



  • fricky schrieb:

    BorisDieKlinge schrieb:

    Hab ne dafür ne Mutex klasse geschrieben:

    wieso schreibt jemand eine klasse für 3 einfach zu verwendende funktionen?
    🙂

    weil der destruktor der klasse unheimlich hilfreich ist



  • raii schrieb:

    weil der destruktor der klasse unheimlich hilfreich ist

    aber das critical-section object ist danach auch ungültig, wenn es ein object-member ist. legt man es statisch an, benutzen alle objecte die selbe CS. das bringt auch nix. also besser keine klasse drum herumstricken.
    🙂



  • 😕 😕 😕 😕 😕



  • class Mutex
    {
        CRITICAL_SECTION *cs;
    
    public:
        Mutex (CRITICAL_SECTION *sect) 
        {
           cs = sect; 
           EnterCriticalSection (cs);
        }
    
        ~Mutex() 
        {
          LeaveCriticalSection (cs);
        }
    };
    ...
    CRITICAL_SECTION the_section;
    ...
    void f()
    {
       Mutex m (&the_section);
       // Locked
       ...
    } // Unlocked
    ...
    

    sinnvoller wäre sowas^^
    🙂



  • Und dein Code funktioniert nicht mal.. Genau deshalb verwendet man Klassen, damit man nicht den Aufruf zu InitializeCriticalSection vergisst. Abgesehen davon ist es doch auch üblich, eine Mutex- und eine MutexLocker- (o.s.ä.) Klasse zu haben.

    edit: übrigens auch und vor allem wegen Exceptions, die überspringen beim "Wurf" ja einfach das "Release".



  • Badestrand schrieb:

    Und dein Code funktioniert nicht mal.. Genau deshalb verwendet man Klassen, damit man nicht den Aufruf zu InitializeCriticalSection vergisst.

    stimmt. ich blindfisch 😞

    Badestrand schrieb:

    Abgesehen davon ist es doch auch üblich, eine Mutex- und eine MutexLocker- (o.s.ä.) Klasse zu haben.

    nö, mein misslungenes beispiel beweisst doch eindeutig, daß man sowas nicht in klassen packen sollte. wo willst du da das InitializeCriticalSection unterbringen?
    🙂



  • Badestrand schrieb:

    edit: übrigens auch und vor allem wegen Exceptions, die überspringen beim "Wurf" ja einfach das "Release".

    unter windows hast du dafür '__finally'
    übrigens ist SEH weitaus nützlich als C++ exceptions
    🙂



  • fricky schrieb:

    Badestrand schrieb:

    Und dein Code funktioniert nicht mal.. Genau deshalb verwendet man Klassen, damit man nicht den Aufruf zu InitializeCriticalSection vergisst.

    stimmt. ich blindfisch 😞

    hihi :p

    fricky schrieb:

    nö, mein misslungenes beispiel beweisst doch eindeutig, daß man sowas nicht in klassen packen sollte. wo willst du da das InitializeCriticalSection unterbringen?
    🙂

    class Mutex{
    
        CRITICAL_SECTION _critSection;
    
    public:
    
        Mutex () { InitializeCriticalSection (& _critSection); }
        ~Mutex () { DeleteCriticalSection (& _critSection); }
    
        void Acquire(){ EnterCriticalSection (& _critSection); }
        void Release(){ LeaveCriticalSection (& _critSection); }
    };
    
    class MutexLocker
    {
        Mutex& cs;
    
    public:
        MutexLocker( Mutex& m ) : cs(m)
        {
           cs.Acquire();
        }
    
        ~MutexLocker()
        {
            cs.Release();
        }
    };
    
    ...
    Mutex the_section;
    ...
    
    void f()
    {
       MutexLocker m (the_section);
       // Locked
       ...
    } // Unlocked
    

    Meinetwegen auch mit "friend", damit man auf Aquire und Release keinen Zugriff mehr hat 🙂



  • fricky halt einfach deine fresse wenn du keine ahnung hast


Log in to reply