Threads mit Klassenmethoden starten



  • class CBasicThread
    {
    public:
        CBasicThread () {}
        ~CBasicThread () {}
        void RunThread (){
          _beginthread ( CBasicThread::StartThread, this, NULL );
    // oder:
          _beginthread ( CBasicThread::StartThread, 0, this );
    // guck selber mal nach, kenne _beginthread nicht, wird aber eines von beiden sein...
        }
        virtual void ThreadFunction() = 0;
    private:
        static void StartThread(LPVOID tmp) {
          ((CBasicThread*) tmp)->TheadFunction();
        }
    }
    
    class myComm : public CBasicThread
    {
        myComm () {}
        ~myComm () {}
        void ThreadFunction() { /* mache irgendwas */ }
    }
    


  • falls die Thread Funktion aber nicht static seien kann (zB. Zugriff auf Klassen Member nötig), dann kannst du auch folgenden Trick nehmen

    #include <iostream>
    
    struct foo {
      static inline void func(foo &this_) 
      { this_.bar(); }
      void bar(void) const { std::cout << "hiho" << std::endl; }
    };
    
    template<class func,class arg>
    void thread(func f,arg &ptr) {
      f(ptr);
    }
    
    int main() {
      foo Foo;
      thread(Foo.func,Foo);
    }
    


  • also der artikel ist gut geeignet http://www.cuj.com/articles/1999/9912/9912d/9912d.htm?topic=articles

    und ein blick auf boost::thread würde vieles einfacher machen



  • also eigendlich gehört das zur Win32- API aber es ist realitiv einfach wenn man auf die Idee kommt. Ich war kürzlich vor dem selben Probelm:

    Das Problem ist das man der Threadfunktion einen Parameter mitliefern muss. Hat man die Threadfunktion allerdings in einer Klasse, wird der Methode automatisch ein this- Zeiger als erstes Argument mitgeliefert und man hat 2 Parameter.

    Mir wurde empfohlen, die methode als static zu machen...allerdings bereitet das nur Kopfschmerzen.... wie wärs damit die Funktion hinter dem Gültigkeitsbereich der Klasse zu definieren...so kann die funktion, die den Thread liefert aus der Klasse gestartet werden und ist gleichzeitig keine Klassenmethode....

    //---------------------------------------------------------------------------------------------
    
    //Die Methode ist dafür verantwortlich für jenden Clienten einen Thread zu erstellen
    void Connection::openNewClientThread ()
    {
    
        //die Threadhandles
        HANDLE  *hThread = new HANDLE [max_clients];
        //die Threadid's
        DWORD *ThreadNr = new DWORD [max_clients];
    
        if (SUCCEEDED (hThread[counter]=   ((HANDLE) _beginthread (ThreadProc,0, (void*) this))))
        {
            cout << "Thread erstellt:    " << hThread[counter];
        }
    
        else
        {
            cout << "Fehler beim Erstellen von Thread für den Clienten" << endl;
    
        }
    
    }
    
    VOID ThreadProc (LPVOID pvoid)
    {
        EnterCriticalSection (&(myCon->cs));
    
        int i_cli= myCon->getCounter ();
    
        pvoid = &((int) i_cli);
    
        int test = *((int*)pvoid);
    
        typedef struct ls
        {
            int* c;
    
        };
    
        ls local;
    
        local.c = (int*) pvoid;
    
        LeaveCriticalSection (&(myCon->cs));
    
        while (TRUE)
        {
    
            //buffer erstellen, der das ergebnis der Methode (also die empfangene Nachricht) auffängt 
            char* ergebnis = myCon->ReadData (local.c);
            if (!ergebnis)
            {
    
                cout << "Nix empfangen" << endl;
                break;
            }
    
            if (strlen (ergebnis) != 0)
            {
    
                cout << ergebnis << endl;
                test = * (int*) pvoid;
                cout << "Strukturindex beim senden ist :  " << test << endl;
                myCon->WriteData (ergebnis, local.c);
            }
    
            strcpy (ergebnis, "\0");        
    
        }
    
    }
    


  • Original erstellt von Parapiler:
    Mir wurde empfohlen, die methode als static zu machen...allerdings bereitet das nur Kopfschmerzen....

    Warum?

    Auch eine static-Funktion kann auf Memberfunktionen und Objekte zugreifen, wenn man ihr einen Zeiger auf ein Objekt (z.B. als Param) mitgibt.

    Wenn Du den Thread über _beginthreadex statt _beginthread startest, kannst Du als Parameter ganz hervorragend den this-Zeiger mitgeben.



  • wo bekommst du myCon her?

    sag jetzt nicht globale variable!

    denk nochmal nach warum wischmop2s Variante die gängiste und beste ist.



  • myCon ist eine Isntanz der Klasse, die muss nicht zwangsläufig global sein. Ich finde sie nicht gerade besser, meine ist einfacher, hat jedoch keinerlei Nachteile, seine ist etwas hochgestochener hat ja auch was....

    muss ja jeder selber wissen...ich finde wo man ohne static auskommt sollte man es auch vermeiden, es ist aber meine meinung dazu, ich mag static nicht.



  • Mit Deiner Vorgehensweise verlierst Du aber die Möglichkeit, in der Funktion auf das Objekt intern zuzugreifen. Also eigentlich genau das, was man manchmal will: eine Memberfunktion soll als Thread laufen können.



  • na über die Klasse kann man dann nicht zugreifen das stimmt noch aber man kann den Thread aus der Klasse auch verändern, da er im globalen Gültigkeitsbereich definiert ist... ist eben nich objektorientiert



  • Bin den weg wischmop2 gegangen ... hat wunderbar funktioniert.
    VIELEN Dank!

    gruss,
    -insane


Anmelden zum Antworten