Multi-threading C++: avviare un Thread più volte?

di il
7 risposte

Multi-threading C++: avviare un Thread più volte?

Sono nuovo nel forum, quindi segnalatemi eventuali miei errori.
Tornando a noi, in sostanza devo avviare un std::thread ogni volta che si verifica una condizione, ho provato in molti modi, ma mi da sempre errori.


while ( !done){
    cout << endl << "Iniziare l'animazione? ";
    cin >> INPUT;
    if (INPUT == "si" ){
        //dovrebbe inizializzare il thread dell'animazione.
    }
}

Vorrei dare più dettagli sull'errore, ma sono passato da poco a Visual Studio e l'errore che mi capita più spesso con questo problema è un "punto di interruzione" e non so come avere più dettagli a riguardo.. (si, ho letto il regolamento, so che dovrei chiedere solo una cosa per post, ma non so dove fare domande riguardo visual studio)

7 Risposte

  • Re: Multi-threading C++: avviare un Thread più volte?

    Scusa, ma puoi postare il codice completo di avvio del thread che ti dà l'errore?

    Comprese dichiarazione di variabili, include ...

    E quale versione di Visual Studio stai usando?
  • Re: Multi-threading C++: avviare un Thread più volte?

    Al momento non ho a portata di mano l'intero codice, per questo ho improvvisato, comunque sto usando l'ultima versione di Visual Studio, il thread gestisce le animazioni di un'entità: ogni tot. Millisecondi deve modificare l'immagine. Può capitare che il thread sia ancora attivo quando lo si reinizializza. Non so se possa essere utile, ma uso Windows 10, libreria grafica SDL2.
  • Re: Multi-threading C++: avviare un Thread più volte?

    No ... non sono informazioni sufficienti, non si è ancora capito il problema ... almeno io non posso darti indicazioni più precise
  • Re: Multi-threading C++: avviare un Thread più volte?

    Ecco il codice:
    
    //Le entità sono di tipo 'Entity'
    class Entity {
    public:
    	int action = codeStill;
    	std::vector <SDL_Texture*> Still;
    	std::vector <SDL_Texture*> Attack;
    	std::vector <SDL_Texture*> Hurt;
    
    	SDL_Rect rect = { 0,0, 200,200 };
    	int anim_state = 0;
    	bool oriented = true; //true=destra, false=sinistra
    
    	int delay[3] = { 500,100 ,200};
    	int NumberOfSprites[3] = { 1, 2, 2 };
    
    	int speed = 3;
    	int range = 10;
    	int Damage;
    	int HP;
    	int full_HP;
    	int ID;
    
    	std::vector <int> Spawn_point = {};
    };
    
    //'First' unica entità al momento esistente.
    Entity First() {
    	Entity obj;
    	extern SDL_Renderer *screen;
    	extern std::vector <Entity> All_Entities;
    
    	//STILL Sprite
    	SDL_Surface *img = IMG_Load("./Sprites/First/still1.png");
    	SDL_Texture *texture = SDL_CreateTextureFromSurface(screen, img);
    	obj.Still.push_back(texture);
    
    	img = IMG_Load("./Sprites/First/still2.png");
    	texture = SDL_CreateTextureFromSurface(screen, img);
    	obj.Still.push_back(texture);
    
    	//ATTACK Sprite
    	img = IMG_Load("./Sprites/First/Attack1.png");
    	texture = SDL_CreateTextureFromSurface(screen, img);
    	obj.Attack.push_back(texture);
    
    	img = IMG_Load("./Sprites/First/Attack2.png");
    	texture = SDL_CreateTextureFromSurface(screen, img);
    	obj.Attack.push_back(texture);
    
    	img = IMG_Load("./Sprites/First/Attack3.png");
    	texture = SDL_CreateTextureFromSurface(screen, img);
    	obj.Attack.push_back(texture);
    
    	obj.Hurt = obj.Attack;
    
    	obj.NumberOfSprites[codeAttack] = 2;
    	obj.action = codeStill;
    	All_Entities.push_back(obj);
    
    	obj.rect = { 1300,500,70,100 };
    
    	obj.speed = 2;
    	obj.Damage = 2;
    	obj.HP = 100;
    	obj.full_HP = 100;
    
    	obj.Spawn_point = { (((rand() % 150 + 110)+2)/3)*3, 120, 120 };
    	return obj;
    }
    
    
    //Questa funzione controlla un'entità la cui posizione nel vettore 'All_Entitites' è indicata dall'argomento 'Check'
    //'int code' indica l'ID dell'entità, per facilitarmi la vita in altre funzioni.
    void Animation_Entities(int Check, int code) {
    	extern std::vector <Entity> All_Entities;
    	extern bool done;
    	extern int Level;
    	extern SDL_Rect wallpaper_pos;
    
    	while (!done) {
    		bool stop = true;
    		while (stop == true) {
    			SDL_Delay(10);
    			switch (Level) {
    			case 0:
    				if (wallpaper_pos.x == All_Entities.at(Check).Spawn_point[Level]) {
    					stop = false;
    					All_Entities.at(Check) = First();
    					break;
    				}
    			}
    		}
    
    		while (All_Entities.at(Check).HP > 0) {
    
    			if (All_Entities.at(Check).anim_state != All_Entities.at(Check).NumberOfSprites[All_Entities.at(Check).action]) {
    				All_Entities.at(Check).anim_state++;
    			}
    			
    			SDL_Delay(All_Entities.at(Check).delay[All_Entities.at(Check).action]);
    			
    		}
    		if (!All_Entities.at(Check).ID == code) {
    			break;
    		}
    	}
    }
    
    //Qui dovrebbe indicare quali entità sono presenti nei vari livelli.
    void UpdateLevel() {
    	extern int Level;
    	extern std::vector <Entity> All_Entities;
    
    	if (Level == 0) {
    		Entity NewEntity = First();
    		NewEntity.ID = 1;
    		NewEntity.HP = 0;
    		All_Entities.push_back(NewEntity);
    		std::thread First_Animation(Animation_Entities, 1, 1); //gestione sprite Prima entità
    
    		NewEntity = First();
    		NewEntity.ID = 2;
    		NewEntity.HP = 0;
    		vector <Entity>::iterator iterator = All_Entities.begin();
    
    		All_Entities.insert(iterator + 2, NewEntity);
    
    		std::thread Second_Animation(Animation_Entities, 2, 2); /gestione Sprite seconda entità
    	}
    }
    
  • Re: Multi-threading C++: avviare un Thread più volte?

    Stai creando dei thread locali a un blocco if che vengono distrutti alla fine di tale blocco. Se non chiami esplicitamente .join() o .detach() il distruttore invoca std::terminate().
    Qui le condizioni: sez. Notes.
    Per evitare questo devi creare le variabili che ospitano i thread fuori da quel blocco, ma esattamente dove dipende dal tuo codice.
    Come hint puoi fare così:
    
    //Qui dovrebbe indicare quali entità sono presenti nei vari livelli.
    void UpdateLevel() {
       extern int Level;
       extern std::vector <Entity> All_Entities;
       std::thread First_Animation; // fuori dal blocco
       std::thread Second_Animation; // fuori dal blocco
    
       if (Level == 0) {
          Entity NewEntity = First();
          NewEntity.ID = 1;
          NewEntity.HP = 0;
          All_Entities.push_back(NewEntity);
          First_Animation = std::thread(Animation_Entities, 1, 1); //gestione sprite Prima entità
    
          NewEntity = First();
          NewEntity.ID = 2;
          NewEntity.HP = 0;
          vector <Entity>::iterator iterator = All_Entities.begin();
    
          All_Entities.insert(iterator + 2, NewEntity);
          Second_Animation = std::thread(Animation_Entities, 2, 2); /gestione Sprite seconda entità
       }
    
       if (First_Animation.joinable()) First_Animation.join();
       if (Second_Animation .joinable()) Second_Animation.join(); 
    }
    
    Tuttavia il codice ha parecchi lati oscuri, per cui se non conosci bene le problematiche del multithreading ti consiglio di studiare bene l'argomento, magari comprando questo:
    https://www.amazon.it/CONCURRENCY-WILLIAMS-ANTHONY-AUTHOR-PAPERBACK/dp/B00974FLRC/ref=sr_1_5?s=books&ie=UTF8&qid=1525100005&sr=1-5
  • Re: Multi-threading C++: avviare un Thread più volte?

    Grazie mille, ora funziona! Ma non ho ancora ben capito detach() a cosa serviva in questo caso..
  • Re: Multi-threading C++: avviare un Thread più volte?

    .detach() si usa quando si vuole che il thread possa esistere anche oltre la fine del main() (se non termina il modo naturale prima).
    Lo puoi pensare (ma non è assolutamente la stessa cosa!) come: "programma che sopravvive al programma che lo ha lanciato e che poi termina".
    Se non si hanno MOLTO ben chiare le problematiche del multithreading, .detach() significa solo cercarsi rogne.

    (Rogne che si presentano anche quando si ha MOLTO ben chiare le problematiche del multithreading)
Devi accedere o registrarti per scrivere nel forum
7 risposte