Probleme mit Threads



  • Hallo,
    ich habe in fogendem Code versucht einen Thread zu erstellen.
    Ich habe versucht die ThreadFunktion in einer Klasse "test" zu deklarieren, damit ich in dem Thread auf member der Klasse zugreifen kann.
    (In diesem Beispiel hat die Klasse keine Member)

    Das Problem ist, dass ich es nicht schaffe dem Thread eine Funktion als Threadfunktion zu geben, die in einer Klasse steht:

    #include <windows.h>
    #include <stdio.h>
    #include <time.h>
    
    #define MAX_THREADS 3 
    
    //Version mit dynamischen Objekten und Zufallszahlen
    
    class Point 
    { 
    
    private: 
        CRITICAL_SECTION CriSect; 
        int m_x; 
        int m_y; 
    public: 
    
        Point () { 
          InitializeCriticalSection(&CriSect); 
        } 
    
    	~Point () {
    		DeleteCriticalSection(&CriSect);
    	}
    
       void setXY(int x,int y) 
       { 
          EnterCriticalSection(&CriSect); 
                m_x = x; 
                m_y = y; 
          LeaveCriticalSection(&CriSect) ; 
    
       } 
       void gibaus() { 
            EnterCriticalSection(&CriSect); 
                printf("%d "  ,(int)m_x  );    
                printf("%d \n",(int)m_y  ); 
            LeaveCriticalSection(&CriSect) ; 
       } 
    
    }; 
    
    class test{								//In dieser Klasse steht die ThreadFunktion
    
    public:
    DWORD WINAPI ThreadFunc(LPVOID data)		
    {
    srand( (unsigned)time( NULL ) );
    	for (int index=0; index<50; index++) {
    		((Point*)data)->setXY(rand() % 100,rand() % 100);	
    		((Point*)data)->gibaus();
    	} 
    	return((DWORD)data);
    	} 
    };
    
    void main(void)
    {
    	test t;
    
    	srand( (unsigned)time( NULL ) );
    
    	Point *p0 = new Point();	
    
    	HANDLE hThread[MAX_THREADS];		
    	DWORD  dwThreadID[MAX_THREADS];		
    
    	printf("\nAlle Threads starten...\n");
    
    for (int index=0; index<MAX_THREADS; index++) { 
    
            hThread[index] = CreateThread(NULL,                        
                                                    0,                            
    												&t.ThreadFunc,    //Und hier möchte ich die Funktion aufrufen und hier entsteht der Fehler           
                                                    (LPVOID)p0,     
                                                    0,                            
                                                    &dwThreadID[index]);    
        } 
    
    	for (int index=0; index<25; index++) {
    
    		p0->setXY(rand() % 100,rand() % 100);
    		p0->gibaus();
    
    	} 
    
    	WaitForMultipleObjects(	MAX_THREADS,
    									hThread,			
    									TRUE,			
    									INFINITE);	
    
    	delete(p0);
    	Sleep(4000);
    
    	for (int index=0; index<MAX_THREADS; index++)
    		CloseHandle(hThread[index]);
    
    	printf("\nAlle Threads beendet.\n");
    
    }
    

    Als Fehler erhalte ich:
    error C2276: '&': Ungültige Operation auf Ausdruck einer gebundenen Memberfunktion

    Wie schaffe ich es eine Methode für den Thread zu verwenden, die in einer Klasse deklariert ist, damit ich auf die dortigen member zugreifen könnte?



  • Funktionen und Methoden sind nicht zuweisungskompatibel. Methoden besitzen immer noch einen unsichtbaren this-Parameter, der ein Zeiger auf die Klasse darstellt. Das gleiche Problem hat man auch in Delphi. Da gibt es allerdinsge inen Trick: Windows-API Callback-Funktion als Methode einer Klasse.



  • Normalerweise verwendet man eine "trampoline-function". Sieht ca. so aus:

    class foo
    {
    public:
        UINT thread_function()
        {
            m_x = 0;
            delete this;
        }
    
    private:
        int m_x;
        // ...
    };
    
    UINT __stdcall trampoline_function(void* p) // <- dashier kannst du jetzt mit _beginthreadex verwenden
    {
        return static_cast<foo*>(p)->thread_function();
    }
    

    Wenn du mehr als nur den "this" Zeiger übergeben willst musst du etwas tricksen. z.B. eine Struktur mit new anlegen wo der this Zeiger drinnen ist plus zusätzliche Parameter. Natürlich musst du dann auch die trampoline_function entsprechend umschreiben. Und irgendwer muss die Struktur auch wieder freigeben - das kann dann z.B. auch die trampoline_function erledigen. Oder du entwirfst deine Klasse einfach so dass keine zusätzlichen Parameter übergeben werden müssen - evtl. kann man die nötigen Werte ja als Member ablegen bevor der Thread gestartet wird.



  • Hi,

    hier auf dieser Wikipedia Seite ist GENAU die Lösung zu deinem Problem.
    (etwas weiter unten, bei dem Kapitel mit dem Titel "Windows")

    http://de.wikipedia.org/wiki/Thread_(Informatik)



  • Danke, genau was ich gesucht habe!!!!! 😃

    (Komisch, ich währe überhaupt nicht auf die Idee gekommen Code Beispiele in Wikipedia zu suchen 😮 )


Anmelden zum Antworten