Struktur als Parameter an Thread übergeben



  • Hallo nochmal,
    ich hätte da eine Frage über das Übergeben von Parametern an Threads.
    Ich habe bisher nur versucht einzelne Parameter an ein Thread zu übbergeben, wobei man es erst nach LPVOID casten musste und im Thread wieder in den gewünschten Typ.

    Jetzt brauche ich aber 2 Parameter und habe mir dafür eine Struktur angelegt und beide Variablen der Struktur ausgefüllt.

    Wenn ich es nun nach LPVOID caste und im Thread zurück gibt es noch keine Fehler, jedoch wenn ich auf eins der beiden Variablen zugreife krieg ein Fehler .

    Jetzt hab ich schon vieles vversucht ,bin aber noch nicht auf eine Lösung gekommen, vielleicht kann mir da einer helfen.

    Hier ist der Codeabschnitt:

    DWORD WINAPI G6_Engine::MeshLoader(LPVOID param)
    {
    	MeshLoaderParam* temp = reinterpret_cast<MeshLoaderParam*>(param);
    
    	std::string temp_name(temp->path);
    
    	MessageBoxA(0,temp_name.c_str(),0,0);
    
    	return 0;
    }
    
    bool G6_Engine::GFileManager::Load(GMesh* mesh, std::string path)
    {
    
    	HANDLE Temp_h = NULL;  //Temp Handle für Thread
    	DWORD  Temp_d = NULL;  //Temp Dword für Thread
    	MeshLoaderParam Temp_param;
    
    	Temp_param.mesh = mesh;
    	Temp_param.path = path;
    
    	Temp_h = CreateThread(NULL, 0 ,(LPTHREAD_START_ROUTINE) MeshLoader,reinterpret_cast<LPVOID>(&Temp_param), NULL, NULL);
    	GetExitCodeThread(Temp_h, &Temp_d);  //In dem Dword wird der Zustand gespeichert
    
    	_ThreadMap.insert( std::make_pair<HANDLE , DWORD>(Temp_h,Temp_d));  //Setze den Thread in die map ein
    
    	return false;
    }
    


  • Hmm also so bekomme ich schonmal keine Fehlermeldung, jedoch hat die Ausgabe keinen Inhalt:

    MeshLoaderParam &c = reinterpret_cast<MeshLoaderParam&>(param);
    
    	std::string temp_name(c.path);
    
    	MessageBoxA(0,temp_name.c_str(),0,0);
    


  • Ein cast von void * nach referenz wird nicht funktionieren.
    versuchs so

    MeshLoaderParam *c = reinterpret_cast<MeshLoaderParam*>(param);
    
        std::string temp_name(c->path);
    
        MessageBoxA(0,temp_name.c_str(),0,0);
    

    Kurt



  • Du übergibst einen Zeiger auf ein lokales Element.
    Wenn G6_Engine::GFileManager::Load() endet bevor G6_Engine::MeshLoader() damit fertig ist wird param ungültig...



  • Ja der Befehl G6_Engine::GFileManager::Load() soll ja nur einen Thread starten und seinen HANDLE bzw. den DWORD zur Überprüfung des States in eine map speichern.Und die Threadfunktion selbst parst und lädt dann ein Mesh, sodass Load() natürlich vor dem Thread fertig ist.

    Was würdet ihr vorschlagen ?? Ich kann alle eingehenden parameter zum laden eines Meshs nicht in der classe speichern (könnte ich schon wäre aber sehr schlecht)... ??



  • Bob Wolfskin schrieb:

    Was würdet ihr vorschlagen ??

    Mit new (evtl. Smartpointer) auf dem Heap anlegen.



  • Und wie genau stellst du dir das vor (mit dem Heap mein ich) ??



  • Meinst du irgendwie sowas:

    MeshLoaderParam *m = new MeshLoaderParam;
         m->mesh = mesh;
    .....
    


  • Yeahh ich habs hinbekommen.Für alle mit dem gleichen Problem:

    DWORD WINAPI G6_Engine::MeshLoader(LPVOID param)
    {
    
    	MeshLoaderParam *c = reinterpret_cast<MeshLoaderParam*>(param);
    
    	std::string temp_name(c->path);
    
    	MessageBoxA(0,temp_name.c_str(),0,0);
    
    	return 0;
    }
    
    bool G6_Engine::GFileManager::Load(GMesh* mesh, std::string path)
    {
    
    	HANDLE Temp_h = NULL;  //Temp Handle für Thread
    	DWORD  Temp_d = NULL;  //Temp Dword für Thread
    	MeshLoaderParam* a = (MeshLoaderParam*) malloc(sizeof(a));
    	new (a) MeshLoaderParam();
    
    	a->mesh = mesh;
    	a->path = path;
    
    	Temp_h = CreateThread(NULL, 0 ,(LPTHREAD_START_ROUTINE) MeshLoader,reinterpret_cast<LPVOID>(a), NULL, NULL);
    	GetExitCodeThread(Temp_h, &Temp_d);  //In dem Dword wird der Zustand gespeichert
    
    	_ThreadMap.insert( std::make_pair<HANDLE , DWORD>(Temp_h,Temp_d));  //Setze den Thread in die map ein
    
    	return false;
    }
    

    Man erstellt erstmal einen Speicherbereich für die Struktur und dann erstellt man mit new eine Instanz davon.Jetzt kann man das ganze ausfüllen und mit reinterpret_cast casten.In dem Thread einfach zurück und man hats



  • Bob Wolfskin schrieb:

    Meinst du irgendwie sowas:

    MeshLoaderParam *m = new MeshLoaderParam;
         m->mesh = mesh;
    .....
    

    Zum Beispiel. ( delete nicht vergessen!)



  • Fehlt nur noch eines

    DWORD WINAPI G6_Engine::MeshLoader(LPVOID param)
    {
    
        MeshLoaderParam *c = reinterpret_cast<MeshLoaderParam*>(param);
    
        std::string temp_name(c->path);
    
        MessageBoxA(0,temp_name.c_str(),0,0);
    
        [b]delete c;[/b] // kann in der aufrufenden funktion nicht freigegeben werden
    
        return 0;
    }
    

    Kurt



  • Bob Wolfskin schrieb:

    MeshLoaderParam* a = (MeshLoaderParam*) malloc(sizeof(a));
    new (a) MeshLoaderParam();
    

    malloc(sizeof(a)) und placement new 😮

    Du reservierst lediglich Platz für einen Zeiger.

    Mach's so, wie Du selbst eben vorschlugst.
    MeshLoaderParam* a = new MeshLoaderParam;



  • malloc(sizeof(a)) und placement new

    Du reservierst lediglich Platz für einen Zeiger.

    Ja so ist das und es funktioniert einwandfrei 😉
    Der Fehler war ja, dass kein Speicherplatz freigegeben wurde und deshalb ein Fehler beim Aufruf die Folge war



  • Bob Wolfskin schrieb:

    Ja so ist das und es funktioniert einwandfrei 😉

    Das denkst Du nur.
    MeshLoaderParam ist größer als ein Zeiger. Du zerschießt dir den Heap. Das kann dir jederzeit um die Ohren fliegen.
    Warum placement new wenn Du doch nur ein new willst?



  • Okey ich habs jetzt umgeschrieben, vielen Dank.
    Übrigens wenn ich in der Threadfunktion meine instanz mit delete am Ende lösche bricht das Program zusammen. 🙂

    Wie kann das sein?



  • Okey machts doch nicht, war nur beim placement new so 😉

    Vielen Dank für die Antworen



  • Bob Wolfskin schrieb:

    Okey machts doch nicht, war nur beim placement new so 😉

    malloc() <-> delete => bumm!


Anmelden zum Antworten