Thread (Wie bekomme ich das hin?)



  • Ich habe die Struktur

    typedef struct ThreadParam_
    { 
     CInteraktion* pInteraktion;
     CIOAbfrage* pAbfrage;
    }ThreadParam;
    

    In eine Extra Haeder Datei. "Struktur.h"
    Diese habe ich dann jeweils in "Interaktion.cpp" und in der "Abfrage.cpp" eingebunden.
    Aus irgendeinen Grund stand das aufeinmal in der "Abfrage.h".

    #include "Struktur.h"	// Hinzugefügt von der Klassenansicht
    

    Das gab nen crash.
    -----
    Was soll ich nun machen? die Membervariable kann ich knicken, weil die Struktur bis dahin unbekannt ist.
    Und wenn ich si vorher einbinde gibt es wieder nen crash



  • ich benutz keine structs
    also mach mal aus der struct ne klasse

    class ThreadParam
    {
    public:
    CInteraktion* pInteraktion;
    CIOAbfrage* pAbfrage;
    };

    binde den header in die cpps ein und in den anderen headern schreibst du nur class ThreadParam;

    #ifndef
    #define

    #endif
    nich vergessen

    dann probiers nochmal



  • (Schade das du keine Strukturen nutzt. Ich fand den Ansatz von Rapha gut.)

    Alles gemacht! jetzt ist nurnoch die Klasse nicht definiert.

    error C2079: 'm_tp' verwendet undefiniertes class 'ThreadParam'

    habe aber "class ThreadParam;" vor die Klasse geschrieben.
    Liegt es an der Klasse selbst? Wußte nicht was ich hier schreiben sollte:

    #ifndef ...
    #define ...

    #endif

    Bei mir sieht es so aus. (Struktur.h)

    #ifndef ThreadParam
    #define run
    
    class ThreadParam
    { 
    public:
     CInteraktion* pInteraktion;
     CIOAbfrage* pAbfrage;
    };
    
    #endif
    


  • #ifndef _H__ThreadParam__H_ //falls dieser header noch nich eingebunden wurde
    #define _H__ThreadParam__H_ //binde ihn jetzt ein

    class ThreadParam
    {
    public:
    CInteraktion* pInteraktion;
    CIOAbfrage* pAbfrage;
    };

    #endif //andernfalls überspringe ihn

    wenn du das nich machst kann es sein, dass du den mehrfachdeklaration-fehler bekommst

    ausserdem musst du den header mit #include in die cpp files einbinden

    bzgl. error C2079: 'm_tp' verwendet undefiniertes class 'ThreadParam'
    d.h. dass du auf membervariablen oder memberfunktionen zugegriffen hast ohne vorher den header einzubinden

    class cBlah;
    cBlah einBlah;// OK
    einBlah.func();//Fehler
    #include "cBlah.h"
    einBlah.func();//OK



  • In die beiden cpp's hab ich sie schon eingebunden (Interaktion.cpp , Abfrage.cpp)

    Soll es auch in die StdAfx.cpp ?

    Außerdem hab ich wie du es sagtest "class ThreadParam;" direkt vor die Klassendefinitionen in (Interaktion.h , Abfrage.h) geschrieben.
    Gibt natürlich auch einen Fehler.

    error C2079: 'm_tp' verwendet undefiniertes class 'ThreadParam'

    Ich glaub wenn das gelöst ist sollte es gehen.



  • ne in die StdAfx muss es nich
    was passiert wenn du statt "class ThreadParam;" den header einbindest?



  • Ein Fehler in meiner Klasse. ---EDIT + weiter 15

    class ThreadParam
    { 
    public:
     CInteraktion* pInteraktion;   <====
     CIOAbfrage* pAbfrage;
    };
    

    error C2143: Syntaxfehler : Fehlendes ';' vor '*'

    ---EDIT
    Bei der anderen Variante hatte ich nur 5 Fehler.



  • schreib mal in deinen ThreadParam header nach dem #define

    class CInteraktion;
    class CIOAbfrage;

    jetzt müssts aber langsam mal gehn oder?



  • 😃
    Es Geht. Glaub ich zumindest. Es wird zwar noch nicht das gemacht was ich will, aber es läuft wie es aussieht.

    Vielen Dank.

    Kann ich noch irgendwie überprüfen ob der Thread läuft?
    Außer Debug?



  • mach halt irgendwas in der watch funktion
    MessageBox("test");



  • Ich glaub jetzt ist das schlimmste passiert was geht!
    Kein Fehler, aber es klappt nicht.

    Was jetzt?
    Mein Thread ändert die Variable (m_iAktuell[]) einfach nicht.
    Die MessageBox geht im übrigen garnicht. bekomme dann einen Fehler:

    'MessageBoxA' : Funktion akzeptiert keine 1 Parameter

    Ist aber Korrekte Syntax. Hab es von einer anderen stelle des Programms einfach kopiert.

    Mit MessageBeep(0); gibt es keinen Fehler, aber es gibt auch keinen Beep.



  • dann halt
    MessageBox(NULL,"test","test",MB_OK);

    und schaum mal ob dein handle nach der create funktion == NULL is



  • Toll. 1000 Fenster wieder schließen. Das macht spaß 😃

    Scheint zu laufen der Thread.
    Wie war das jetzt mit dem handle?
    Wo soll ich da nachsehen?



  • Hi,

    ich habe einmal versucht dein Problem zu rekonstruieren.
    Schau dir mal das Projekt an: headfinger_thread.zip
    http://mitglied.lycos.de/rame03/files.htm

    Hast du soetwas gemeint?

    Grüße Rapha



  • Geil. Das sich jemand soviel mühe für mich macht finde ich wirklich klasse 🙂
    Danke. Ich werde es gleich an meine Anwendung anpassen und dann nocheinmal schreiben wie es läuft. Sieht aber nahezu perfekt aus.

    Nur eine Frage noch.
    Warum wird der Thread sofort beendet? Wird er doch, oder?

    Ich schau mal was bei mir passiert. 😉

    ---------- EDIT ------------
    😞
    Ich verstehe nicht warum der Thread nicht läuft.
    Oder er läuft, aber er macht nicht das was ich will.

    Habe an deinem Projekt zwei kleinigkeiten geändert. Schau mal.

    void CExeDlg::OnAction() 
    {
    	for (int i=0;i<4;i++)
    	{
    	m_pInteraktion->LesePermament();
    
    	Sleep(500); // NUR ZU TESTZWECKEN (sonst lieber Mutexe verwenden): Warten, bis Threadfunktion
    	            // beendet ist
    	CString strTemp;
    	strTemp.Format("Inhalt von m_a[0] des CInteraktion-Objektes: %d", m_pInteraktion->m_a[0]);
    	MessageBox(strTemp);
    	}
    }
    

    und hier

    UINT CAbfrage::Watch(LPVOID pParam)
    {
    	CInteraktion* pInteraktion = (CInteraktion*) pParam;
    		pInteraktion->m_a[0] = 0;
    	{
    	pInteraktion->m_a[0]++;
    	AfxMessageBox("CAbfrage::Watch() beendet");
    	}while(TRUE);
    
    	return 1;
    }
    

    Was ich damit Bezwecke ist glaube ich klar.
    Ich will ein paar MessageBoxen haben die mir je einen anderen Wert bringen.
    Geht aber nicht.

    PS. Sollte nicht in den Thread ein Sleep() eingebaut sein?



  • Hi,

    setzt mal das while an den Anfang des Blocks:

    CInteraktion* pInteraktion = (CInteraktion*) pParam; 
            pInteraktion->m_a[0] = 0; 
        while(TRUE){ 
        pInteraktion->m_a[0]++; 
        AfxMessageBox("CAbfrage::Watch() beendet"); 
        };
    

    Viel Spaß beim Klicken 😃

    Grüße Rapha



  • 😮
    Bin ich blöd.
    Oder auch nicht?
    Dachte echt das kommt ans Ende. Aber es läuft.
    Das war echt super von dir. Kann ich dir nen Kaffe spendieren? Ich mach auch nen Kuchen dazu. 🙂

    Endlich. Mein erster Thread der läuft.
    Das versuche ich nächst Woche gleich nochmal, und dann versuch ich es ohne Hilfe

    BYE und DANK an
    Rapha und
    Sovok



  • gern geschehn 🙂



  • Nu doch noch eine Frage zum Thema.

    Wie beende ich einen Thread?
    m_pWatchThread->ResumeThread()
    Startet ihn ja bei mir,
    und wie halte ich ihn an bzw., wie Zerstöre ich ihn?

    Das ich innerhalb der Tread Funktion "AfxEndThread" benutzen muß weiß ich aber mir fällt keine Bedingung ein.

    Oder gibt es ne andere Lösung?



  • Hi,

    du musst den Thread von innen heraus beenden (=>AfxEndThread oder return).
    D.h. du musst ein Mutex (=>CMutex) oder ähnliches verwenden, das gesetzt wird, wenn die Threadfunktion beendet werden soll.

    Ich erlaube mir einfach etwas aus der MSDN zu kopieren:

    MSDN schrieb:

    Zwei normale Situationen führen dazu, daß ein Thread terminiert wird: Die Steuerungsfunktion wird beendet oder der Thread darf nicht vollständig ausgeführt werden. Falls z. B. eine Textverarbeitung einen Thread für den Hintergrunddruck verwendet, wird die Steuerungsfunktion normal beendet, sobald der Druckauftrag erfolgreich abgeschlossen ist. Sollte nun aber der Hintergrunddruck durch den Benutzer abgebrochen werden, müßte der Thread für den Hintergrunddruck vorzeitig terminiert werden. Dieser Artikel beschreibt, wie jede Situation zu implementieren ist und wie der Beendigungs-Code des Threads nach seiner Terminierung ermittelt wird.

    Normale Thread-Terminierung

    Vorzeitige Thread-Terminierung

    Ermitteln des Beendiguns-Codes eines Threads
    Normale Thread-Terminierung
    Die normale Thread-Terminierung für einen Worker-Thread ist einfach: Beendigung der Steuerungsfunktion und Rückgabe eines Wertes, der den Grund für die Terminierung angibt. Sie können entweder dieAfxEndThread-Funktion oder eine return-Anweisung verwenden. In der Regel bedeutet 0 erfolgreiche Ausführung, aber dies ist ganz Ihnen überlassen.

    Für einen Benutzeroberflächen-Thread ist der Vorgang entsprechend einfach: Rufen Sie innerhalb des Benutzeroberflächen-Threads die Funktion::PostQuitMessage auf, die in der Win32 Programmer‚s Reference, Volume 4 beschrieben wird. Der einzige Parameter, den ::PostQuitMessage erwartet, ist der Beendigungs-Code des Threads. Wie bei Worker-Threads bedeutet 0 in der Regel erfolgreiche Ausführung.

    Vorzeitige Thread-Terminierung
    Die vorzeitige Terminierung eines Threads ist fast genauso einfach: Rufen SieAfxEndThread innerhalb des Threads auf. Übergeben Sie den gewünschten Beendigungs-Code als einzigen Parameter. Dadurch wird die Ausführung des Threads beendet, der Stack des Threads freigegeben, alle an den Thread gebundenen DLLs getrennt und das Thread-Objekt aus dem Speicher gelöscht.

    AfxEndThread muß innerhalb des zu terminierenden Threads aufgerufen werden. Wenn Sie einen Thread von einem anderen Thread aus terminieren möchten, müssen Sie ein Kommunikationsverfahren zwischen den beiden Threads einrichten.

    Ermitteln des Beendigungs-Codes eines Threads
    Um den Beendiguns-Code des Worker- oder Benutzeroberflächen-Threads zu erhalten, rufen Sie die::GetExitCodeThread-Funktion auf. Weitere Informationen über diese Funktion finden Sie in der Win32 Programmer‚s Reference, Volume 3. Diese Funktion besitzt die Zugriffsnummer zu dem Thread, (der im m_hThread-Datenelement des CWinThread-Objekts gespeichert ist) sowie die Adresse eines DWORD.

    Falls der Thread noch aktiv ist, wird STILL_ACTIVE von ::GetExitCodeThread in der bereitgestellten DWORD-Adresse abgelegt; ansonsten wird der Beendigungs-Code in dieser Adresse abgelegt.

    Die Ermittlung des Beendigungs-Codes von CWinThread-Objekten erfordert einen zusätzlichen Schritt. Standardmäßig wird ein Thread-Objekt gelöscht, sobald ein CWinThread-Thread terminiert wurde. Dies bedeutet, daß Sie nicht mehr auf das m_hThread-Datenelenment zugreifen können, da das CWinThread-Objekt nicht mehr existiert. Sie können diese Situation vermeiden, indem Sie eine der folgenden zwei Methoden anwenden:

    Setzen Sie das m_bAutoDelete-Datenelement auf FALSE. Dies ermöglicht ein Fortbestehen des CWinThread -Objekts, nachdem der Thread terminiert wurde. Sie können dann auf das m_hThread -Datenelement zugreifen, nachdem der Thread terminiert wurde. Bei dieser Methode sind Sie jedoch auch für die Zerstörung des CWinThread-Objekts verantwortlich, da es das Gerüst nicht automatisch löscht. Dies ist die bevorzugte Methode.
    – oder –

    Speichern Sie die Zugriffsnummer des Threads separat. Kopieren Sie nach der Erstellung des Threads sein m_hThread-Datenelement (mit Hilfe von ::DuplicateHandle) in eine andere Variable, und greifen Sie über die Variable darauf zu. Auf diese Weise wird das Objekt automatisch bei der Terminierung gelöscht, und Sie haben dennoch die Möglichkeit, den Grund für die Terminierung des Threads zu erfahren. Achten Sie darauf, daß der Thread nicht terminiert wird, bevor Sie die Zugriffsnummer duplizieren können. Am sichersten ist es, zunächst CREATE_SUSPENDED anAfxBeginThread zu übergeben, die Zugriffsnummer zu speichern und anschließend den Thread durch Aufrufen vonResumeThread wieder aufzunehmen.
    Mit jeder der beiden Methoden läßt sich ermitteln, warum ein CWinThread-Objekt terminiert wurde.

    Grüße Rapha


Anmelden zum Antworten