Threads in Klassen



  • Fiesek schrieb:

    Da kann ich dir nur teilweise zustimmen, dass mein Code nicht funzt.

    Es geht nicht darum, ob du mir zustimmst oder nicht. Dein Code ist falsch. Punkt. Und wenn dein Compiler das übersetzt, dann ist er diesbezgl. kaputt.
    Und wenn du das noch immer nicht akzeptierst, dann beantworte mir doch mal folgende Frage:
    Wie du sicherlich weisst, liegt jeder Member-Funktion (in deinem Fall X::Threadxyz) ein Objekt zu Grunde. Dieses lässt sich in der Funktion über this ansprechen und wird ausserhalb beim Aufruf explizit angegeben. Da CreateThread genau das macht, dh X::Threadxyz irgendwann aufruft, muss es also ein Objekt geben. Ich sehe in deinem CreateThread Aufruf allerdings keines. Du etwa? Und &X::Threadxyz, wie es übrigens korrekterweise heissen muss, ist nur ein Funktionszeiger. Mit Objekt is hier nix.



  • Sry, ihr habt recht, ich hab unrecht.
    Mein Code funzt definitiv nicht!



  • So, ich hab meine Threads jetzt static gemacht und siehe da, es funzt.

    Wichtig dabei:

    static nur in der Deklaration angeben,
    der Thread kann nun nicht mehr auf Elementfunktionen und Membervariablen der eigenen Klasse zugreifen.

    Ich hab meinen Threads dann ein Array von Pointern auf meine Membervariablen mitgegeben.
    So ließ es sich dann fehlerfrei compilieren.



  • Du hast dir aber schon meinen ersten Beitrag durchgelesen? Dort hab ich doch erklärt, wie du eine Memberfunktion für deine Threadfunktion verwenden kannst und damit auch auf Membervariablen zugreifen kannst.



  • Hab im Moment etwas ähnliches am Laufen: Meine Threadfunktion ist als statische Methode in meiner Klasse, jedes Objekt hat eine Funktion zum Starten des Threads. Dabei wird natürlich immmer ein Zeiger zum Objekt selbst übergeben.
    In der Threadfunktion befindet sich eine Endlosschleife.
    Meine Frage: Können diese Objekte nun tatsächlich unabhängige Threads haben? Will heißen laufen parallel mehrere Aufrufe der statischen Funktion und wenn ja, wie hängen diese zeitlich miteinander zusammen?



  • Wenn Du mehrere Threads startest, dann laufen auch mehrere! Zeitlich hängen die gar nicht zusammen. Wenn Du was synchronisieren musst, dann musst Du dies selber machen... (CriticalSections, Events, ...)



  • Das ist mir schon klar, ist in dem Falle nicht einmal nötig.
    Mir ging es nur um die Frage ob die Threads der einzelnen Objekte unabhängig laufen, obwohl es ja die gleiche statische Funktion ist und diese sozusagen mehrmals gleichzeitig läuft.



  • Wenn Du unterschiedliche Pointer auf die Klasse übergeben hast (also "this"), dann hat ja die statische Thread-Funktion auch diesen Pointer. Somit verwendet jeder Thread die Klasse welche Du übergeben hast. Da dies ja ein Parameter ist, der auf dem Stack liegt und jeder Thread seinen eigenen Thread hat ist sie in jedem Thread eben anders (wenn Du was anderes übergeben hast).



  • Ich habe mal eine kleine Testklasse für so etwas geschrieben um das mal zu beobachten:

    class ThreadObject{
      public:
        ThreadObject(int _id, HWND _hParent) { id = _id; hParent = _hParent;};
        void startWatch(void)
        {
            _beginthread(appWatch,0,(void *)this);
        }
    
      private:
        int id;
        HWND hParent;
    
        static void appWatch(void *tObject)
        {
          ThreadObject *obj = static_cast<ThreadObject*>(tObject);
    
          for(;;){
            Sleep(500 + (rand() % 5) * 100);
            SendMessage(obj->hParent,WM_THREAD_OBJECT_NOTIFY,(WPARAM)obj->id,NULL);
          }
        }
    };
    

    Sorry wegen der Klassen, ist aber in eine normale WinAPI Anwendung eingebettet.

    Man holt sich mit

    ThreadObject *obj = new ThreadObject(1001,hwnd);
    obj->startWatch();
    

    (Sorry wegen new 😃 )

    ein ThreadObject und startet mit startWatch() den Thread dieses Objekts. Der Thread eines jeden Objekts schickt nun in relativ zufälligen Abständen eine Nachricht mit seiner id an das Hauptfenster, welches diese recht simpel ausgibt.

    Dabei ist beim Benutzen von mehr als einem Objekt zu beobachten, dass die Nachrichten der Objekte immer stoßweise ankommen. Also zb so:

    Nachricht id 1; 
    Nachricht id 2; 
    Nachricht id 3;
    
    [600 millisec vergehen]
    
    Nachricht id 1;
    Nachricht id 2;
    Nachricht id 3;
    
    [1000 millisec vergehen]
    
    Nachricht id 1;
    Nachricht id 2;
    Nachricht id 3;
    
    [1100 millisec vergehen]
    
    Nachricht id 1;
    Nachricht id 2;
    Nachricht id 3;
    

    Die Abstände sind zufällig, jedoch sind sie bei allen Objekten gleich. Liegt das vielleicht sogar daran, dass der Zufallsgenerator bei paralellen Aufrufen die gleiche Zahl ausspuckt? Kann ich mir nicht vorstellen.



  • Du hast vergessen den rand zu initialisieren, deswegen liefert er in allen Thread immer die gleichen Abfolgen an Zahlen und somit treten die Events immer gleichzeitig ein...
    =>

    static void appWatch(void *tObject)
        {
          ThreadObject *obj = static_cast<ThreadObject*>(tObject);
    
          srand( (unsigned)time( NULL ) );
    
          for(;;){
            Sleep(500 + (rand() % 5) * 100);
            SendMessage(obj->hParent,WM_THREAD_OBJECT_NOTIFY,(WPARAM)obj->id,NULL);
          }
        }
    


  • Sorry, wollte nicht den ganzen Code posten.
    randomize() wird in WM_CREATE aufgerufen!



  • Du musst den random in *jedem* Thread initialisieren! Also bringt es nix wenn Du dies in WM_CREATE machst (da dies ja ein ganz anderer Thread ist!).
    Auch wenn Du es in dem Thread machst, und Du die Threads ganz schnell hintereinader startest, kann es sein dass der gleiche Seed verwendet wird.... also füge noch irgendein globaler Zähler hinzu...



  • Der Randomgenerator ist also nicht global, nichtmal innerhalb eines Prozesses!

    Ich habe das Initialisieren jetzt mal in jedem Thread vorgenommen. Das bringt auch noch nix. Fügt man jedoch wie du sagtest einen Counter, der pro Initialisierung um sagen wir 100 erhhöt wird, zu time hinzu wird das gewünschte Ergebnis erzielt.

    Interessante Sache, vielen Dank für die Tipps...

    ~nirsaja



  • Jochen Kalmbach schrieb:

    Du musst den random in *jedem* Thread initialisieren!

    Nein, eigentlich nicht. Es reicht einmal beim Programmaufruf.
    Oder irr ich mich? Bin mir nicht 100% sicher.

    mfg.



  • joomoo schrieb:

    Jochen Kalmbach schrieb:

    Du musst den random in *jedem* Thread initialisieren!

    Nein, eigentlich nicht. Es reicht einmal beim Programmaufruf.
    Oder irr ich mich? Bin mir nicht 100% sicher.

    Du irrst Dich (debugge doch einfach mal in srand rein, dann siehst Du es)


Anmelden zum Antworten