Thread erzeugen.



  • Hallo.
    Ich habe folegendes Problem. Ich habe eine Klassenhierachie, bestehend aus verschiedenen Klassen ( Klasse A, Klasse B usw). Nun möchte ich eine neue Intanz einer KLasse erzeugen. Das klappt auch ganz gut. Diese Klasse (Konstruktor) führt dabei gleich mehrere Sachen aus. Ich mächte nun sehr viele Instanzen dieser Klasse erzeugen und sie parallel abarbeiten lassen.
    Dazu habe ich mir überlegt jede Instanz in einem Thread laufen zu lassen.
    Der Aufruf der Instanz erfolgt bisher so.

    cMatch *match = new cMatch(liga->Get_Ansetzungen(spieltag)[spiele]);
    

    Ich habe mich bereits etwas beslen und weiß das die Funktion zum Aufrufen eines Threads als static deklariert werden muss. Allerdings bekomme ich immer einen Fehler wenn ich versuche den Konstruktor als static zu deklarieren.
    Ich hoffe meine Erklärungen waren ausführlich genug. Kann mir jemand helfen. Ich möchte keinen fertigen Quellcode ( ich weiß dafür sind die Erklärungen zu ungenau. Sonder nur einen Hinweis wie man vorgehen muss)
    Vielen Dank für eure Bemühungen



  • Der Konstruktor ist die Methode, die zum Initialisieren einer INSTANZ dient. static heißt aber, dass du auf die Methode ohne jegliche Instanziierung zugreifen kannst. Beides beißt sich. erstelle eine statische Methode, die eine Instanz erzeugt und zurück liefert. Die kannst du dann threaden.



  • Hallo.
    Vielen Dank für deinen Tipp. WErde ihn gelcih ausprobieren.



  • Die meisten Thread-APIs erwarten einen Funktionszeiger mit einer bestimmten Signatur. Diese Signatur beinhalten eigentlich so gut wie immer einen void* als Parameter, um beliebige Inhalten in die ausgelagerte Funktion hinbekommen zu können. Hier kann man einen this-Pointer übergeben, und den dann in der Threadfunktion in den passenden Klassenpointer zurückcasten.
    Das ermöglicht Dir, innerhalb der statischen Methode mit Instanzen zu arbeiten.

    Beispiel:

    //CreateThread soll so aussehen (ist nur ein Beispiel)
    //typedef void(*runProc)(void*)
    //void CreateThread(runProc proc, void* param);
    
    class ThreadableClass
    {
    public:
    	ThreadableClass()
    	{
    		CreateThread(run, this);
    	}
    
    	void doSomething()
    	{
    		//...
    	}
    private:
    	static void run(void* param)
    	{
    		ThreadableClass* instance = reinterpret_cast<ThreadableClass*>(parem);
    		//...
    		instance->doSomething();
    	}
    };
    


  • Hallo.
    ICh habe eure Tipps umgesetzt und kann nun eine Thread erzeugen. Allerdings würde ich nun gerne eine Funktion einer Klasse als Thread - Funktion benutzen.

    Allerdings bekomme ich da immer einene Fehler :

    error C2664: 'CreateThread' : cannot convert parameter 3 from 'void (void *)' to 'unsigned long (__stdcall *)(void *)'
            None of the functions with this name in scope match the target type
    

    Der Aufruf der folgt so :

    HANDLE hThread[1];
    	hThread[0] = CreateThread(NULL,0,test_thread,NULL,0,NULL);
    	WaitForMultipleObjects(1,hThread, true,INFINITE);
    

    UNd die Definition ist :

    class cVolleyballTrainer
    {
    public:
    
    	cVolleyballTrainer(string odbc);
    	void Neues_Spiel();
    
    private:
    	static void test_thread(LPVOID pr)
    	{
    		cout<<"TEST!!!!!!";
    	}
    	//static DWORD test(void* pr);
    };
    

    Ich hoffe ihr könnt mir helfen .
    Vielen Dank



  • static DWORD test_thread(LPVOID pr)
    {
    //...
    }
    

    nicht

    static void test_thread(LPVOID pr)
    {
    //...
    }
    


  • Vielen Dank für deine Antwort. Aber dsa Fehlerbild ist das gleiche.



  • Probier mal:

    static DWORD WINAPI test_thread(PVOID pr)
    


  • Klasse . Das wars, vielen Dank,



  • Okay nach dem ich nun die FUnktion als thread aufrufen kann möchte ich auch auf die Klassen variblen zugreifen. Wie geht das ?

    Hier noch mal der Aufruf :

    HANDLE hThread[10];
    	int a = 10;
    	hThread[0] = CreateThread(NULL,0,test_thread,(void*)a,0,NULL);
    	WaitForMultipleObjects(1,hThread, true,INFINITE);
    

    Und die Definition :

    class cVolleyballTrainer
    {
    public:
    
    	cVolleyballTrainer(string odbc);
    	void Neues_Spiel();
    
    private:
    	static DWORD WINAPI test_thread(LPVOID pr);
    
    	cLiga *liga;
    };
    

    Und ich will jetzt auf

    liga
    

    zugreifen in meiner Threadfunktion . Wie gth das ??

    Vielen Dank



  • Habe ich oben beschrieben.



  • Okay. Ich habe mir deinen Beitrag noch einmal angesehen. Aber wenn ich das richtig sehe übergibts du der Funktion ja einen Paramter. Ich möchte aber ohne Paraterübergabe auf eine Variable zugriefen.

    Ist das überhaupt möglic ?



  • Nein, Deine Thread-Methode ist statisch, das heisst, sie ist von konkreten Objekt-Instanzen unabhängig.
    Um Zugriff darauf zu bekommen, musst Du einen this-Pointer übergeben.
    Btw. übergibst Du im Moment ja auch einen Parameter (int a).



  • Sofern Du die MS -CRT verwendest, solltest Du nicht CreateThread nutzen sondern _beginthreadex

    Ich vermute, aber, dass diesin anderen Compilern mit deren CRTs ähnlich ist.
    http://blog.m-ri.de/index.php/2007/11/28/createthread-und-die-crt/
    http://blog.m-ri.de/index.php/2008/02/28/afxbeginthread-versus-_beginthreadex/



  • GUten Morgen .
    Nachdem ich nun die Threads erzeugen konnte möchte ich nun auf ihre Abrabeitung warten.
    Ich erzeuege die Threads wie folgt :

    threadLiga *x = new threadLiga;
    	x = (threadLiga*)pr;
    
    	HANDLE hThread[5];
    	//cout<<x->iSpieltag<<"\n";
    	for (int i = 0; i < 5; i++)
    	{
    
    		threadLiga *temp = new threadLiga;
    		temp->iSpielnummer = i;
    		temp->iSpieltag = x->iSpieltag;
    		temp->pLiga = x->pLiga;
    
    		hThread[i] = CreateThread(NULL,0,Spiele_Match,(void*)temp,0,NULL);
    
    	}
    
    	WaitForMultipleObjects(5,hThread, true,INFINITE);
    

    MIt der Funktion Waitfor MultipleObjects warte ich auf das Ende der jeweiligen Threads leider kommt dabei eine Exception. Wenn ich in der Schleife auf die Beendigung warte( jeden einzelen) dann geht es .HAt jemand einen Idee.

    Vielen Dank



  • albert-einstein2 schrieb:

    Ich erzeuege die Threads wie folgt :

    threadLiga *x = new threadLiga;
    	x = (threadLiga*)pr;
    

    Schönes Speicherleck.

    albert-einstein2 schrieb:

    temp->pLiga = x->pLiga;
    

    Der Name pLiga deutet auf einen Zeiger hin. Wenn du nur einen Zeiger kopierst, dann benutzen alle Threads dasselbe Objekt. Ist das beabsichtigt, und hast du die Zugriffe synchronisiert?

    albert-einstein2 schrieb:

    MIt der Funktion Waitfor MultipleObjects warte ich auf das Ende der jeweiligen Threads leider kommt dabei eine Exception.

    Geht's etwas genauer als "eine Exception"?

    albert-einstein2 schrieb:

    Wenn ich in der Schleife auf die Beendigung warte( jeden einzelen) dann geht es

    Weil dann alle Threads nacheinander ablaufen. Dann hättest du dir die Threads auch sparen können. Also vermutlich wirklich ein Synchronisierungsproblem.



  • MFK schrieb:

    albert-einstein2 schrieb:

    Ich erzeuege die Threads wie folgt :

    threadLiga *x = new threadLiga;
    	x = (threadLiga*)pr;
    

    Schönes Speicherleck.

    Warum ist das ein Speicherleck ?

    Ansonsten hast du recht pLiga ist ein Zeiger. Ja das ist so beasichtigt. Der HIntergrund ist der : pLiga ist ein Zeiger auf eine Liga . Meine Thread Funtkion soll nun für diese Liga von einem bestimmten Spieltag (iSpieltag) alle Spiel ausführen (ebenfalls als Thread) deshalb müssen alle Thread sauf den gleiehn Zeiger zugriefen.



  • albert-einstein2 schrieb:

    Warum ist das ein Speicherleck ?

    An das Objekt, das du da mit new erzeugst, kommst du nie wieder ran, weil du gleich danach den Zeiger auf ein anderes Objekt umbiegst. Du kannst es also nie wieder freigeben -> Speicherleck.

    albert-einstein2 schrieb:

    Meine Thread Funtkion soll nun für diese Liga von einem bestimmten Spieltag (iSpieltag) alle Spiel ausführen (ebenfalls als Thread) deshalb müssen alle Thread sauf den gleiehn Zeiger zugriefen.

    Wie gesagt, du hast offenbar ein Synchronisierungsproblem. Für weitere Diagnose hast du nicht genug Informationen geliefert.



  • Okay danke für deine Antwort.

    Hier noch ein paar zusätzlich iNfos

    HANDLE hThread[1];
    
    	for (int i = 1; i <= liga->Get_Spieltag(); i++)
    	{
    		threadLiga *sp = new threadLiga;
    		sp->pLiga = liga;
    		sp->iSpieltag = i;
    
    		hThread[0] = CreateThread(NULL,0,test_thread,(void*)sp,0,NULL);
    
    	}
    
    	WaitForMultipleObjects(1,hThread, true,INFINITE);
    
    }
    
    // ==========================================
    
    DWORD WINAPI cVolleyballTrainer::test_thread(LPVOID pr)
    {
    	threadLiga *x = new threadLiga;
    	x = (threadLiga*)pr;
    
    	HANDLE hThread[5];
    	//cout<<x->iSpieltag<<"\n";
    	for (int i = 0; i < 5; i++)
    	{
    
    		threadLiga *temp = new threadLiga;
    		temp->iSpielnummer = i;
    		temp->iSpieltag = x->iSpieltag;
    		temp->pLiga = x->pLiga;
    
    		hThread[i] = CreateThread(NULL,0,Spiele_Match,(void*)temp,0,NULL);
    
    	}
    
    	WaitForMultipleObjects(5,hThread, true,INFINITE);
    
    	return 1;
    }
    
    // ==========================================
    
    DWORD WINAPI cVolleyballTrainer::Spiele_Match(LPVOID data)
    {
    	threadLiga *x = new threadLiga;
    	x = (threadLiga*)data;
    
    	//cout<<x->pLiga->Get_Ansetzungen(x->iSpieltag)[x->iSpielnummer]->pHeim->Get_Name()<<" "<<x->pLiga->Get_Ansetzungen(x->iSpieltag)[x->iSpielnummer]->pGast->Get_Name()<<"\n";
    	try
    	{
    		cMatch *ma = new cMatch(x->pLiga->Get_Ansetzungen(x->iSpieltag)[x->iSpielnummer]);
    		x->pLiga->Set_Ergebnis(ma->Get_Ergebnis());
    	}
    	catch(cException *ex)
    	{
    		cout<<ex->sError<<"\n";
    	}
    
    	return 1;
    }
    


  • Und weiter?
    Sind Get_Ansetzungen und Set_Ergebnis ordentlich synchronisiert, oder ist das Prinzip Hoffnung?
    Ist dir klar, dass du bei jedem Spiele_Match-Aufruf auch noch ein cMatch-Objekt erzeugst, das nie wieder freigegeben wird?

    Warum machst du das überhaupt mit Threads, und nicht einfach nacheinander?



  • Weil es 1. zu lange dauert. Und 2. Ich etwas lernen möchte.

    // ==========================================
    
    DWORD WINAPI cVolleyballTrainer::Spiele_Match(LPVOID data)
    {
    	threadLiga *x = new threadLiga;
    	x->iSpielnummer = ((threadLiga*)pr)->iSpielnummer;
    	x->iSpieltag = ((threadLiga*)pr)->iSpieltag;
    	x->pLiga = ((threadLiga*)pr)->pLiga;
    
    	//cout<<x->pLiga->Get_Ansetzungen(x->iSpieltag)[x->iSpielnummer]->pHeim->Get_Name()<<" "<<x->pLiga->Get_Ansetzungen(x->iSpieltag)[x->iSpielnummer]->pGast->Get_Name()<<"\n";
    	try
    	{
    		cMatch *ma = new cMatch(x->pLiga->Get_Ansetzungen(x->iSpieltag)[x->iSpielnummer]);
    		x->pLiga->Set_Ergebnis(ma->Get_Ergebnis());
    		delete ma;
    	}
    	catch(cException *ex)
    	{
    		cout<<ex->sError<<"\n";
    	}
    
    	return 1;
    }
    

    Wäre das so besser.
    Also mit dem Speicherlecks und dem Freigeben ?
    Vielen Dank


Anmelden zum Antworten