Thread innerhalb von Klasse



  • hi, ich hab ne klasse geschrieben, die mit mit mehreren threads arbeiten soll.
    wenn ich jetzt mit CreateThread einen Thread starte und die einen Zeiger auf eine Funktion meiner Klasse übergebe, dann bringt er mir einen Fehler, dass er irgendwas anderes erwartet. Wenn die übergebene Funktion nicht zur KLasse gehöhrt, dann geht es einwandfrei.
    weiss jemand was ich machen muss dass des geht?

    thx, Cypher



  • Also ohne jetzt ein Thread-Spezialist zu sein, kann ich dazu folgendes sagen:
    Die Informationen sind unzureichend

    Du solltest zumindest etwas Code und die genaue Fehlermeldung posten.



  • Also die Fehlermeldungen sind folgende:

    [C++ Error] portscanner.cpp(55): E2034 Cannot convert 'unsigned long (__stdcall * (_closure )(void *))(void *)' to 'unsigned long (__stdcall *)(void *)'
    [C++ Error] portscanner.cpp(55): E2342 Type mismatch in parameter 'lpStartAddress' (wanted 'unsigned long (__stdcall *)(void *)', got 'unsigned long (__stdcall * (_closure )(void *))(void *)')

    und etwas code

    class PortScanner
    {
            private:
                    DWORD WINAPI ScanThread( LPVOID Data );
    
            public:
                    void StartScan( void );
    }
    
    void PortScanner::StartScan( void )
    {
            HANDLE hThread[MAX_THREADS];
            DWORD dwThreadID[MAX_THREADS];
    
            for (int index=0; index<MAX_THREADS;index++)
            {
                    hThread[index] = CreateThread( NULL,
                                                   0,
                                                   &ScanThread,
                                                   (LPVOID)index,
                                                   0,
                                                   &dwThreadID[index]
                                                 );       
            }
    }
    
    DWORD WINAPI PortScanner::ScanThread( LPVOID Data )
    {
            return (DWORD) Data;
    }
    

    Wenn ScanThread nicht Teil der Klasse is, dann gehts



  • siehe
    www.function-pointer.org

    Eine Memberfunktion hat als ersten Parameter immer this.
    Insofern ist sie nicht kompatibel mit einer non-member Funktion.

    Beispiel:
    void foo()
    hat die Signatur void ()();
    während
    void Foo::foo()
    die Signatur
    void (Foo::
    )()
    hat.



  • hast du da zufällig auch n link auf deutsch? 🙄

    is das ein großer aufwand, oder muss ich da nur irgend ne zeile ändern?
    wenn ja... welche? 🙂



  • Naja, schau mal:

    void foo();
    ist eine einfache Funktion, kein this Zeiger.
    void Foo::foo()
    hat aber einen. Es sieht intern deshalb so aus:
    void foo(Foo* const this);

    und genau diesen Zeiger müssen wir Rechnung tragen.

    Ich vereinfache CreateThread mal auf CreateFoo. CreateFoo nimmt als 1. Parameter einen Zeiger auf eine Funktion:
    DWORD f(void*) - genau wie CreateThread. Als zweiten Parameter übergibt man diesen void*.

    Soweit alles klar?

    Dann kann man:

    CreateFoo(&Scanner::Scanhandler, new Scanner(bla) );
    

    Scanhandler muss static sein - damit es keinen this Zeiger hat:

    static DWORD Scanner::Scanhandler(void* p)
    {
      return static_cast<Scanner*>(p)->scan();
    }
    

    Jetzt kann in Scanner::scan die Aktion ausgeführt werden.

    Statt die Daten über den void* zu übergeben, übergibst du die Daten dem Konstruktor von Scanner (new Scanner(bla)).



  • Also jetzt hast du mich so richtig verwirrt 😮

    was heisst denn dieses static, static_cast und <...*>



  • ich hab jetzt lediglich aus
    DWORD WINAPI ScanThread( LPVOID Data );

    static DWORD WINAPI ScanThread( LPVOID Data );
    gemacht... und er bringt mir wenigstens keine compilerfehler mehr...
    was dieses static_cast macht hab ich glaub ich rausgefunden (Typumwandlungen, oder?), aber was macht dieses static?



  • Cypher schrieb:

    was dieses static_cast macht hab ich glaub ich rausgefunden (Typumwandlungen, oder?), aber was macht dieses static?

    Siehe http://tutorial.schornboeck.net/casts.htm
    und http://tutorial.schornboeck.net/staticmember.htm

    Sorry wenn ich dich verwirrt habe - aber diese Lösung ist die gängigste - und es lohnt sich aufjedenfall wenn du sie einmal kapiert hast 🙂 Muss ja nicht jetzt sein, kannst ja einfach eine static Memberfunktion nehmen und eben nicht mit einer Klasse direkt arbeiten.



  • Hey, vielen Dank, das funktioniert jetzt (soweit ich das überschauen kann) so wie ich will.
    Allerings übergeb ich der Funktion ScanThread jetzt nicht mehr diesen index, dondern einen this zeiger, und diese gibt grundsätzlich 0 zurück. ist dieser index irgendwie wichtig, oder kann ich das so lassen?

    also im moment siehts so aus:

    DWORD WINAPI PortScanner::ScanThread( void *Data );
    
    hThread[index] = CreateThread( NULL,
                                   0,
                                   &ScanThread,
                                   this,
                                   0,
                                   &dwThreadID[index]
                                 );
    


  • Nimm nicht CreateThread, nimm _beginthreadex.
    CreateThread ist in C++ Programmen fast nie sinnvoll, weil die Standard-Lib nichts vom Erstellen des Threads mitbekommt.


Anmelden zum Antworten