Thread in Visual C++ / MFC



  • Vielen Dank WebNubbi,

    sehr interessant die Links, aber das scheint mir die C-Version zu sein und mir ist nicht klar, wie ich die mit meiner Klasse bzw. deren Methode zusammenbringe... 😕

    Gibts es denn nicht evt. etwas, was zu der Klassengeschichte besser paßt? - wo ich einfach meine Methode angebe (die z.B. nicht den Typ "__stdcall" 😕 hat...) und los geht's? Ich muß aus der Methode heraus ja auch auf alle Mitglieder meiner Dialogklasse zugreifen können...



  • Wenn Du schon MFC verwendest, dann solltest Du auch die MFC-Thread-Klasse verwenden:
    http://msdn.microsoft.com/library/en-us/vclib/html/_MFC_CWinThread.asp



  • da ich von dem ganzen Kram nicht wirklich was verstehe, wäre ein vollständies Beispiel für mich sehr wichtig! Ein Beispiel, das kurz ist und kompiliert!!!

    Wenn ich die anderen Beispiele (z.B. die FAQs) anschaue und das Zeug eingebe, dann gibt es im Wesentlichen irgendwelche Compiler-Fehler!! 😞 Daraus kann ich leider auch nichts lernen. Diese Objektorientierung ist mir ein Rätsel... 😕

    Daher muß ich alles (Zeile für Zeile / bitte nichts weglassen) wissen, was ich eintippen muß damit der Thread startet und ich nicht mit kryptischen Fehlermeldungen überschüttet werde... ich fürchte sonst wird das nix... wäre supernett, fallls jemand so ein vollständiges Beispiel für mich hätte!! Vielen Dank!!



  • wo kommt in FAQs -zum Thema Thread- denn z.B. das "m_pDisplayThread" her und was ist das? Ich benötige da die Definition...

    Oder die "threadklasse" mal mit Stern und mal ohne?!?!?!? Ich brauche diese threadklasse - wo steht die und wie sieht die aus?!?!? 😕



  • Du erstellst eine neue Klasse. Diese leitest du von CWinThreads ab.
    Der Rest ist der Code aus der FAQ.
    In der abgeleiteten Klasse musst du die RUN-Methode noch hinzufügen.
    Geht alles über Vc++ und klicki bunti.



  • Leider versteh ich von objektorientierter Programmierung nicht viel! und von der krausen syntax von Visual C++ noch weniger... 😞 Ich arbeite eigentlich nur mit Funktionen. Mein Problem ist nun, daß ich (auch unter Zuhilfenahme einschlägiger Bücher) keine Klasse ableiten kann ohne daß es Fehlermeldungen hagelt! Ich kann bei den vielen Deklarationen/Definitonen kein System erkennen! Und dann diese Namen!!! 😞 CMyObjekt* MyObject = (CMyObject 😉 MyObject;... Alles sieht gleich aus!!! Oder Typen wie LOVOID!?!??!...

    Deshalb brauche ich ein kleines funktionierendes Beispiel, das ich via cut&paste übernehmen und dann meine eigene Funktionalität aus meiner Funktion reinkopieren kann. Vielleicht tut's das dann...

    Gut gemeinte Erklärungen: "...mach dies und dann das..." nützen mir so leider nichts 😞

    Wäre super nett wenn sich jemand erbarmen und mir ein solches (kurzes) Beispiel schicken würde! 🕶



  • In die Funktion, die den Thread startet schreibst du:

    m_pWinThread = ::AfxBeginThread (ThreadFunc, this); 
    
    	if(m_pWinThread)
    	{
    		//Thread wurde erstellt.
    	}
    	else
    	{
    		//Thread wurde nicht erstellt.
    	}
    

    m_pWinThread ist eine Member Variable vom Typ CWinThread - also wird im Header File folgendermaßen definiert:

    CWinThread *m_pWinThread;
    

    ThreadFunc ist dabei die Funktion, die im Thread aufgerufen wird. Kannst du natürlich abändern wie du willst, jedoch muss ThreadFunc so definiert werden:

    .h File:

    static UINT ThreadFunc(LPVOID lpParameter);
    

    .cpp File:

    UINT CDeinDlg::ThreadFunc (LPVOID lpParameter)
    {
    
    CDeinDlg *Dlg	= (CDeinDlg *)lpParameter;	
    // Diese Funktion wird aufgerufen.
    // mit Dlg-> kannst du auf Funktionen/Variablen zugreifen
    }
    

    CDeinDlg natürlich anpassen.

    Wie du oben siehst wird 'this' als einziger Parameter mitgegeben - dadurch kannst du auf Funktionen und Variablen des Hauptdialogs zugreifen.

    In der ThreadFunc beendest du den Thread mit

    ::AfxEndThread(1, TRUE);
    

    Natürlich solltest du dir eine Abbruch Bedingung überlegen .. z.B.: beim Starten des Threads wird eine Variable auf 1 gesetzt. Die Thread Funktion überprüft nun die Variable in einer Schleife, sobald die Variable gleich 0 ist, rufst du AfxEndThread auf.



  • ST schrieb:

    Leider versteh ich von objektorientierter Programmierung nicht viel! ... Mein Problem ist nun, daß ich keine Klasse ableiten kann ohne daß es Fehlermeldungen hagelt!

    Wenn du nicht viel von OOP verstehst, warum arbeitest du mit Klassen?

    Ich kann bei den vielen Deklarationen/Definitonen kein System erkennen! Und dann diese Namen!!! 😞 CMyObjekt* MyObject = (CMyObject 😉 MyObject;... Alles sieht gleich aus!!!

    Das sind Grundlagen.

    Deshalb brauche ich ein kleines funktionierendes Beispiel, das ich via cut&paste übernehmen und dann meine eigene Funktionalität aus meiner Funktion reinkopieren kann.

    Du meinst, die Hilfe muss so aussehen, dass du selbst nicht mehr denken musst?

    Wie wäre es denn, wenn du das eine oder andere Grundlagentutorial durcharbeiten würdest? Zuerst eins für Standard-C++/OOP, und dann eins für MFC? IMHO hast du da noch ziemlich große Lücken.



  • Ich versuchs trotzdem nochmal (IMHO die einfachste Variante ):

    Alles was Du brauchst steht in der MSDN unter AfxBeginThread:

    UINT MyThreadProc( LPVOID pParam )
    {
        CMyObject* pObject = (CMyObject*)pParam;
    
        if (pObject == NULL ||
            !pObject->IsKindOf(RUNTIME_CLASS(CMyObject)))
        return 1;   // if pObject is not valid
    
        // do something with 'pObject'
    
        return 0;   // thread completed successfully
    }
    
    // inside a different function in the program
    .
    .
    .
    pNewObject = new CMyObject;
    AfxBeginThread(MyThreadProc, pNewObject);
    

    In deinem Fall wäre es wohl so am einfachsten:

    Du deklarierst in deiner Dialogklasse (.h) die Threadfunktion (MyThreadProc) wie folgt:

    public:
        static UINT MyThreadProc( LPVOID pParam );   //LPVOID ist dabei ein Zeiger auf eine beliebige Struktur
    

    dann definierst Du die Funtion in der cpp-Datei deiner Dialogklasse(hab ich einfach mal CMyDialog genannt) etwa so:

    UINT CMyDialog::ThreadProc( LPVOID pParam )
    {
        CMyDialog* pMyDialog = (CMyDialog*) pParam; //Da ist es wieder dieses eigenartige Konstrukt ;) (TypeCast) da wirst Du aber nicht drumherumkommen
        while(true) //i.d.R. wirst Du dir hier eine schlauere Abbruchbedingung einfallen lassen müssen ;)
        {
            pMyDialog->... ;// an dieser Stelle kannst Du jede public Methode deines Dialogs aufrufen
        }
        return 0;
    }
    

    Jetzt hast Du schon fast Alles, was noch fehlt ist der Start des Threads:

    Also z.B in einer OnButtonClicked deines Dialoges:

    void CMyDialog::OnButtonClicked()
    {
        AfxBeginThread( MyThreadProc, this );
    }
    

    Vieleicht wird Dir jetzt auch die Sache mit dem Cast klarer. AfxBeginThread benötigt als Threadfunktion genau den Prototypen wie oben beschrieben, bei der Übergabe des this- Pointers wird automatisch auf LPVOID 'gecastet' um das rückgängig zu machen benötigst Du einfach diese Zeile:

    CMyDialog* pMyDialog = (CMyDialog*) pParam;
    

    Im einzelnen bedeutet das:
    erzeuge einen Zeiger pMyDialog auf den Typ CMyDialog ( CMyDialog* pMyDialog )
    Wandle pParam (Typ LPVOID) um, in einen Zeiger auf den CMyDialog ( (CMyDialog*)pParam )
    weise pMyDialog diesen Zeiger zu (=) 😉

    So, eigentlich sollte das Alles sein ich hoffe es hilft Dir auch ein bisschen.

    mfg

    connan

    Edit: Hier waren ja mal wieder einige schneller 🙄



  • 😮 WOW!!! Ihr seid ganz große Klasse!!! 👍

    ES FUNKTIONIERT!!!!! SUPER - genauso wollt' ich's haben!!! Puuuuhhhhh

    VIELEN HERZLICHEN DANK!!!!

    Besonders der Beitrag von WinThread hat enorm viel gebracht!!!! Aber auch von connan hab' ich was gelernt!

    So - da die Geschichte im Wesentlich läuft, werd' ich mich mal an den Feinschliff machen...

    Stimmt es eigentlich, daß der Thread automatisch gestoppt wird, falls man den aufrufenden Prozeß beendet (also das Programm schließt)?

    Noch ein paar Worte zu MFK:

    Wenn du nicht viel von OOP verstehst, warum arbeitest du mit Klassen?

    Weil ich einen Dialog unter Win2000/XP brauche und dachte, daß das mit MFC einfacher geht, als wenn ich direkt mit den API-Funktionen hantiere... 🙄

    Das sind Grundlagen.

    OK - ganz so schlimm ist es auch nicht, aber ich versteh halt nicht, warum alle die Dinge unnötig kompliziert und unverständlich machen müssen. Man kann auch klarere Namen vergeben... Das erinnert mich ein bischen ein C-Programmier, die einen ganzen texteditor in eine Zeile gequetscht haben...

    Du meinst, die Hilfe muss so aussehen, dass du selbst nicht mehr denken musst?

    Genau - zumindest, wenn es sich um ein 0815-Problem handelt, das schon tausendmal gelößt wurde und eigentlich auch niemand wirklich interessiert. Es soll einfach nur funktionieren, damit man sich um die eigentlichen Probleme kümmern kann... ...und schnell sollte es auch gehen... 😃

    Wie wäre es denn, wenn du das eine oder andere Grundlagentutorial durcharbeiten würdest? Zuerst eins für Standard-C++/OOP, und dann eins für MFC? IMHO hast du da noch ziemlich große Lücken.

    Mach ich vielleicht auch - andererseits lerne ich am besten am konkretes Problem und 2. durch freundliche Zeitgenossen, die mich an ihrem reichen Wissensfundus teilhaben lassen. Trockene Grundlagentutorials sind nicht unbedingt mein Fall...


Anmelden zum Antworten