IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

 C Discussion :

Sockets dans un thread, mais application toujours bloquée..


Sujet :

C

  1. #1
    Membre régulier Avatar de theclem35
    Homme Profil pro
    Technicien Réseaux & Télécommunications
    Inscrit en
    Décembre 2007
    Messages
    148
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Vendée (Pays de la Loire)

    Informations professionnelles :
    Activité : Technicien Réseaux & Télécommunications
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Décembre 2007
    Messages : 148
    Points : 86
    Points
    86
    Par défaut Sockets dans un thread, mais application toujours bloquée..
    Salut!

    Voila j'utilise les sockets dans mon application et comme j'ai des fonctions bloquantes (recvfrom) j'ai placé tout ca dans un thread.

    Maitenant quand je clique sur mon bouton j'appelle le thread.

    Seul problème c'est que mon appli reste figée, mon bouton enfoncé !
    Bref aucune difference par rapport a avec ou sans thread !

    Pouvez vous m'aider ?

    Le code de mon thread (enfin juste le début car après c'est les sockets..) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    DWORD WINAPI HebergementPartie(void * thPartie) // Avec un thread on a un type void * (on peut mettre ce qu'on veut)
    {
          InfosPartie * PartieCree = thPartie; // On indique qu'on veut travailler sur une structure InfosPartie pour notre variable e/s
    [....] // Le reste du code ...
    Mon appel :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
        InfosPartie MaPartie;
        HANDLE hdlThreadServeur;
        DWORD CodeRetourThread;
     
                   hdlThreadServeur = CreateThread(NULL, 0, HebergementPartie, &MaPartie, 0, NULL); // On lance le thread pour une ecoute UDP en attente de demande d'infos, ou de connexion
                   // faire une animation d'attente
                   WaitForSingleObject(hdlThreadServeur, INFINITE); // On attend que le thread se finisse naturellement
                   GetExitCodeThread(hdlThreadServeur, &CodeRetourThread); // Puis on recupere le code de retour du thread
                   if(CodeRetourThread != -1)
                   {
                         // On ferme toutes les fenetres et on demarrer la partie
                   }
    Je vois pas trop ce qui coche !

  2. #2
    Membre chevronné
    Profil pro
    Inscrit en
    Août 2006
    Messages
    1 104
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 1 104
    Points : 1 750
    Points
    1 750
    Par défaut
    Salut

    Il y a bien trop peu de code pour qu'on puisse répondre.

  3. #3
    Membre régulier Avatar de theclem35
    Homme Profil pro
    Technicien Réseaux & Télécommunications
    Inscrit en
    Décembre 2007
    Messages
    148
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Vendée (Pays de la Loire)

    Informations professionnelles :
    Activité : Technicien Réseaux & Télécommunications
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Décembre 2007
    Messages : 148
    Points : 86
    Points
    86
    Par défaut
    Coucou! Oui j'ai mis le principal car le reste n'a rien avoir et fonctionne parfaitement.

    Voila pour plus de details :

    Ma fonction hebergementPartie :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    DWORD WINAPI HebergementPartie(void * thPartie) // Avec un thread on a un type void * (on peut mettre ce qu'on veut)
    {
          InfosPartie * PartieCree = thPartie; // On indique qu'on veut travailler sur une structure InfosPartie pour notre variable e/s
          int CodeErreur; // Code d'erreur des fonctions
          int ReponseConnexion;
          int TailleStructure; // Taille de la structure serveur
          char TexteErreur[120]; // Pour insérer le message d'erreur des socket dans la msgbox
          int LongueurMessage; // Nombre de caracteres
          char Tampon[65535]; // Tampon pour les données reçues ou envoyées
          SOCKET idSocket; // Identifiant de la socket
          SOCKADDR_IN InfosServeur, InfosClient; // Structure contenant les infos du serveur
     
          idSocket = socket(AF_INET,SOCK_DGRAM,0); // On ouvre la socket en UDP
          if (idSocket == INVALID_SOCKET)
          {
                   sprintf(TexteErreur,"Impossible de creer la socket du à l'erreur : %d",WSAGetLastError());
                   MessageBox(NULL,TexteErreur,"Erreur Générale !",MB_OK | MB_ICONERROR);
                   return -1; // On termine la fonction et renvoi -1 pour prevenir l'appli principale
          }
     
          /* Config Infos Serveur */  
          InfosServeur.sin_family = AF_INET;
          InfosServeur.sin_addr.s_addr = INADDR_ANY; // Ecoute sur toutes les IPs 
          InfosServeur.sin_port = htons(PORT_SERVICE_SERVEUR); // Ecoute sur le port 1337
          /* ******************* */
     
          CodeErreur = bind(idSocket,(struct sockaddr*)&InfosServeur,sizeof(InfosServeur)); // On bind la socket
          if (CodeErreur != 0)
          {
                sprintf(TexteErreur,"Impossible d'écouter ce port du à l'erreur : %d",WSAGetLastError());
                MessageBox(NULL,TexteErreur,"Erreur Générale !",MB_OK | MB_ICONERROR);
                closesocket(idSocket);
                return -1;
          }
     
          TailleStructure = sizeof(InfosServeur); // Taille de la structure car pointeur dans le recvfrom
     
          while(1)
          {
                  LongueurMessage = recvfrom(idSocket,Tampon,1515,0,(struct sockaddr*)&InfosClient,&TailleStructure);
                  if (LongueurMessage == SOCKET_ERROR)
                  {
                         sprintf(TexteErreur,"Impossible de recevoir les données du à l'erreur : %d",WSAGetLastError());
                         MessageBox(NULL,TexteErreur,"Erreur Générale !",MB_OK | MB_ICONERROR);
                         closesocket(idSocket);
                         return -1;
                  }
                  Tampon[LongueurMessage] = 0; // On rajoute \0 pour fermer la chaine
     
                  if(!strcmp(Tampon, "DECOUVERTE")) // On envoie la structure de la partie créée et on continue à écouter
                  { 
                         LongueurMessage = sendto(idSocket, (char*)PartieCree, sizeof(InfosPartie),0,(struct sockaddr*)&InfosClient,TailleStructure);
                         if (LongueurMessage == SOCKET_ERROR)
                         {
                                 sprintf(TexteErreur,"Impossible d'envoyer les données du à l'erreur : %d",WSAGetLastError());
                                 MessageBox(NULL,TexteErreur,"Erreur Générale !",MB_OK | MB_ICONERROR);
                                 closesocket(idSocket);
                                 return -1;
                         }
     
                  }
                  else if(!strcmp(Tampon, "CONNEXION"))
                  {                
                         sprintf(TexteErreur,"Le client avec l'IP %s a demandé à se connecter\nAccepter ?",inet_ntoa(InfosClient.sin_addr));
                         ReponseConnexion = MessageBox(NULL,TexteErreur,"Connexion entrante",MB_YESNO | MB_ICONQUESTION); // Messagebox avec oui/non sous forme de question
     
                         if (ReponseConnexion == 6) // Si on accepte le client (OUI vaut 6)
                         {
                                 strcpy(Tampon,"CONNEXIONACCEPTEE"); // Copie la chaine de caractère dans buffer
                                 LongueurMessage = sendto(idSocket,Tampon,strlen(Tampon),0,(struct sockaddr*)&InfosClient,sizeof(InfosClient)); // On envoie la sequence CONNACCEPT pour accepter la client
                                 if (LongueurMessage == SOCKET_ERROR)
                                 {
                                         sprintf(TexteErreur,"Impossible d'envoyer les données du à l'erreur : %d",WSAGetLastError());
                                         MessageBox(NULL,TexteErreur,"Erreur Générale !",MB_OK | MB_ICONERROR);
                                         closesocket(idSocket);
                                         return -1;
                                 }
     
                                 LongueurMessage = recvfrom(idSocket,Tampon,1515,0,(struct sockaddr*)&InfosClient,&TailleStructure); // On recoit le nom du joueur2 pour remplir la structure
                                 if (LongueurMessage == SOCKET_ERROR)
                                 {
                                        sprintf(TexteErreur,"Impossible de recevoir les données du à l'erreur : %d",WSAGetLastError());
                                        MessageBox(NULL,TexteErreur,"Erreur Générale !",MB_OK | MB_ICONERROR);
                                        closesocket(idSocket);
                                        return -1;
                                 }
                                 Tampon[LongueurMessage] = 0; // On rajoute \0 pour fermer la chaine
     
                                 strcpy(PartieCree->PseudoJ2, Tampon); // On rempli la structure avec le pseudo du Joueur 2
                                 strcpy(PartieCree->IPClient, inet_ntoa(InfosClient.sin_addr)); // SOn adresse IP ...
     
                                 break; // ... On a toutes les infos, on arrete l'ecoute UDP et on passe en TCP pour la partie
                         }
                         else
                         {
                                 strcpy(Tampon,"CONNEXIONREFUSEE"); // Copie la chaine de caractère dans buffer
                                 LongueurMessage = sendto(idSocket,Tampon,strlen(Tampon),0,(struct sockaddr*)&InfosClient,sizeof(InfosClient)); // On envoie la sequence REFUSER pour refuser le client
                                 if (LongueurMessage == SOCKET_ERROR)
                                 {
                                         sprintf(TexteErreur,"Impossible d'envoyer les données du à l'erreur : %d",WSAGetLastError());
                                         MessageBox(NULL,TexteErreur,"Erreur Générale !",MB_OK | MB_ICONERROR);
                                         closesocket(idSocket);
                                         return -1;
                                 } 
                         }
                  }
          }
     
          CodeErreur = closesocket(idSocket); // On ferme la socket qui a été ouverte
          if (CodeErreur != 0)
          {
                sprintf(TexteErreur,"Impossible de libérer la socket du à l'erreur : %d",WSAGetLastError());
                MessageBox(NULL,TexteErreur,"Erreur Générale !",MB_OK | MB_ICONERROR);
                return -1;
          }
     
          return 0; // Tout s'est bien passé
    }
    Et la fonction qui gere mon bouton :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    void GestBoutonsFHebergerPartie(HWND fenetre,UINT message, WPARAM wParam, LPARAM lParam)
    {
        char NomPartie[256],PortSaisi[6],NomJoueur1[13],IPChoisie[16],NiveauChoisi[3];
        int PortConverti;
        InfosPartie MaPartie;
        HANDLE hdlThreadServeur;
        DWORD CodeRetourThread;
     
        switch(LOWORD(wParam)) // Quand btn enfoncé, une partie de wParam vaut Id du bouton => recup avec LOWORD()
        {
        case ID_LANCER_SERVEUR:
             GetDlgItemText(fenetre, ID_NOM_PARTIE, NomPartie, 23); // On recupere toutes les valeurs entree par le joueur
             GetDlgItemText(fenetre, ID_COMBOBOX_LISTEIPS, IPChoisie, 16);
             GetDlgItemText(fenetre, ID_PORT_CHOISI, PortSaisi, 6);
             GetDlgItemText(fenetre, ID_COMBOBOX_LISTENIVEAUX, NiveauChoisi, 3);
             GetDlgItemText(fenetre, ID_PSEUDO_JOUEUR1, NomJoueur1, 13);
             sscanf(PortSaisi, "%d", &PortConverti); // Obligé de faire une conversion char->int pour tester si le port est correct
     
             if((PortConverti < 1025) || (PortConverti > 65535))
             {
                   MessageBox(NULL,"Le port doit être compris entre 1024 et 65535 !","Erreur !",MB_OK | MB_ICONWARNING);
             }
             else if(NomPartie[0] == '\0') // On teste si le 1er caractere est une fin de chaine, autrement dit si elle est nulle
             {
                   MessageBox(NULL,"Veuillez spécifier un nom pour votre partie...","Erreur !",MB_OK | MB_ICONWARNING);
             }
             else if(NomJoueur1[0] == '\0')
             {
                   MessageBox(NULL,"Veuillez spécifier votre pseudo !","Erreur !",MB_OK | MB_ICONWARNING);
             }
             else
             {
                   strcpy(MaPartie.NomPartie, NomPartie); // On remplie la structure qu'on enverra sur le reseau en reponse aux broadcasts
                   strcpy(MaPartie.IPServeur, IPChoisie);
                   strcpy(MaPartie.Port, PortSaisi);
                   strcpy(MaPartie.Niveau, NiveauChoisi);
                   strcpy(MaPartie.PseudoJ1, NomJoueur1);
     
                   // probabilité d'erreur sur taille de la structure Partie en (char *) dans sockets alors que pointeur
     
                   hdlThreadServeur = CreateThread(NULL, 0, HebergementPartie, &MaPartie, 0, NULL); // On lance le thread pour une ecoute UDP en attente de demande d'infos, ou de connexion
                   // faire une animation d'attente
                   WaitForSingleObject(hdlThreadServeur, INFINITE); // On attend que le thread se finisse naturellement
                   GetExitCodeThread(hdlThreadServeur, &CodeRetourThread); // Puis on recupere le code de retour du thread
                   if(CodeRetourThread != -1)
                   {
                         // On ferme toutes les fenetres et on demarrer la partie
                   }
             }
            break;
        case ID_QUITTER_HEBERGEMENT:
            ShowWindow(fenetre, SW_HIDE);
            break;
        }
    }
    En fait on dirait (on dirait seulement) que c'est ma fonction WaitForSingleObject(hdlThreadServeur, INFINITE); qui bloque mon programme alors que normalement les threads sont faits pour eviter ca !
    Je ne comprend pas ce qui se passe.

  4. #4
    Membre chevronné
    Profil pro
    Inscrit en
    Août 2006
    Messages
    1 104
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 1 104
    Points : 1 750
    Points
    1 750
    Par défaut
    Apparemment, GestBoutonsFHebergerPartie est la fonction callback de ta fenêtre, qui gère les événements (clic bouton sur tel bouton, ...). Si tu lances un autre thread et que tu bloques le thread principal avec un WaitForSingleObject, c'est normal que plus rien ne réagisse, puisque les messages Windows (gestion clics, redimensionnement, rafraichissement, etc) ne peuvent plus être gérés dans la boucle principale (qui, elle aussi, est gelée), ni traités par la fonction callback... et ce jusqu'à ce que le second thread soit terminé.

    EDIT :
    En principe, tu ne dois pas bloquer le thread courant. Le but est justement de faire tourner plusieurs thread. Si tu appuies sur un bouton pour lancer une fonction dans un second thread, tu peux par exemple griser le bouton, le temps que la fonction s'exécute, puis le rendre cliquable une fois que le thread est fini. (Ca dépend ce que tu veux faire)

  5. #5
    Membre régulier Avatar de theclem35
    Homme Profil pro
    Technicien Réseaux & Télécommunications
    Inscrit en
    Décembre 2007
    Messages
    148
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Vendée (Pays de la Loire)

    Informations professionnelles :
    Activité : Technicien Réseaux & Télécommunications
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Décembre 2007
    Messages : 148
    Points : 86
    Points
    86
    Par défaut
    Oui c'est bien la fonction callback (enfin du moins celle qui gere les WM_COMMAND)

    Du coup comment faire pour mettre mes sockets dans un autre thread sans bloquer ma fenetre principale ?
    Dans ce que tu as dis, j'ai compris que WaitForSingleObject est une fonction bloquante ?????? Du coup aucun interet d'utiliser les threads??????

    Le probleme c'est que si je n'appelle pas WaitForSingleObject et que je lance mon serveur, le port est bien ouvert et il est apparament en ecoute, sauf que j'ai des données complètement incohérente quand je me connecte en client sur le serveur, alors que ca marche très bien d'habitude...

  6. #6
    Membre chevronné
    Profil pro
    Inscrit en
    Août 2006
    Messages
    1 104
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 1 104
    Points : 1 750
    Points
    1 750
    Par défaut
    Le probleme c'est que si je n'appelle pas WaitForSingleObject et que je lance mon serveur, le port est bien ouvert et il est apparament en ecoute, sauf que j'ai des données complètement incohérente quand je me connecte en client sur le serveur, alors que ca marche très bien d'habitude...
    Oui, car il y a un gros soucis dans ton code : les variables locales à ta fonction callback. Lorsqu'un message Windows est choppé par la boucle principale, la fonction callback est lancée, puis on quitte, et on retourne dans la boucle. Or, tu envoies à ton second thread l'adresse d'un objet local à ta fonction callback... qui est détruit juste après.

  7. #7
    Membre régulier Avatar de theclem35
    Homme Profil pro
    Technicien Réseaux & Télécommunications
    Inscrit en
    Décembre 2007
    Messages
    148
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Vendée (Pays de la Loire)

    Informations professionnelles :
    Activité : Technicien Réseaux & Télécommunications
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Décembre 2007
    Messages : 148
    Points : 86
    Points
    86
    Par défaut
    Je ne comprends pas.

    La fonction qui envoie les données a mon thread, est la fonction appellée uniquement en cas de WM_COMMAND (donc btn, je te mets la callback générale de la fenetre ci-dessous)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    LRESULT CALLBACK procedureFenetreHebergerPartie(HWND fenetre, UINT message, WPARAM wParam, LPARAM lParam)
    {
        char MesIPs[10][17]; // On cree un tableau de 10 IPs max car 10 cartes reseau c'est deja pas mal....
        int i,NbIPsLocales;
        NbIPsLocales = RecupererMesIPs(MesIPs);
     
        switch (message)
        {
        case WM_CREATE:
            RemplirFenetreHebergerPartie(fenetre);
            for(i=0;i<NbIPsLocales;i++)
            {
                  SendDlgItemMessage(fenetre, ID_COMBOBOX_LISTEIPS, CB_ADDSTRING, 0, (LONG)MesIPs[i]); // on envoie la liste des ips dans la combo
            }
            SendDlgItemMessage(fenetre, ID_COMBOBOX_LISTEIPS, CB_SETCURSEL, 0, 0); // selectionne une ip
            for(i=0;i<6;i++)
            {
                  SendDlgItemMessage(fenetre, ID_COMBOBOX_LISTENIVEAUX, CB_ADDSTRING, 0, (LONG)"1"); // on rempli la combo avec les niveaux
            }
            SendDlgItemMessage(fenetre, ID_COMBOBOX_LISTENIVEAUX, CB_SETCURSEL, 0, 0); // selectionne automatique 1er niveau
            SendDlgItemMessage(fenetre, ID_NOM_PARTIE, EM_SETLIMITTEXT,(WPARAM)22, (LPARAM)0); // limite le nb de caracteres a 22
            SendDlgItemMessage(fenetre, ID_PORT_CHOISI, EM_SETLIMITTEXT,(WPARAM)5, (LPARAM)0); // limite le nb de caracteres a 5
            SendDlgItemMessage(fenetre, ID_PSEUDO_JOUEUR1, EM_SETLIMITTEXT,(WPARAM)12, (LPARAM)0); // limite le nb de caracteres a 12
            return 0;
        case WM_COMMAND: // Quand un bouton est enfoncé message = WM_COMMAND
            GestBoutonsFHebergerPartie(fenetre,message,wParam,lParam);
            return 0;
        case WM_CLOSE:
            ShowWindow(fenetre, SW_HIDE); // Fermer fenetre et non detruire
            return 0;
     
        default:
            return DefWindowProc(fenetre,message,wParam,lParam);
        }
    }
    D'apres ce que je comprends, de toutes facon je n'ai certainement pas besoin d'appeller WaitForSingleObject ca ne sert absolument a rien.
    Donc j'enleve ce bout, mais ca ne m'explique pas les caracteres bizarres que je recois dans mon client, effectivement si j'appuyais encore une fois sur le bouton qui lance le thread je veux bien.

    Tu as certainement raison mais une connexion ne se fait pas entre 2 neurones de mon cerveau

  8. #8
    Membre chevronné
    Profil pro
    Inscrit en
    Août 2006
    Messages
    1 104
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 1 104
    Points : 1 750
    Points
    1 750
    Par défaut
    Je ne comprends pas.

    La fonction qui envoie les données a mon thread, est la fonction appellée uniquement en cas de WM_COMMAND (donc btn, je te mets la callback générale de la fenetre ci-dessous)
    Oui, mais une fois que le message WM_COMMAND est traité, on sort de la fonction pour retourner dans la boucle.

    En fait, dans un programme fenêtré (sous Windows, en tout cas), il y a une boucle principale, en attente d'un message lancé par l'OS, qui se rajoute dans la file de messages (quand on redimensionne ou déplace la fenêtre, quand on clique, quand la fenêtre doit être rafraichie, etc). Dès que la boucle trouve un message, elle provoque l'exécution de la fonction callback afin de gérer ce message. Ce message est ensuite supprimé de la file de messages, afin de gérer le suivant (s'il y en a un, sinon la boucle attend). Or, dans la partie de code qui gère WM_COMMAND tu exécute ta fonction GestBoutonsFHebergerPartie, qui, elle, créée ton second thread, en lui envoyant l'adresse d'un objet local à cette fonction, puis, pendant que le second thread est exécuté, les deux fonctions GestBoutonsFHebergerPartie et procedureFenetreHebergerPartie quittent.
    Le problème, c'est que la fonction de ton second thread (HebergementPartie) manipule un objet qui était local à la fonction qui vient juste de quitter et qui n'existe plus désormais. A tout moment, la pile d'exécution peut empiler d'autres données, qui n'ont plus rien à voir avec ce que fait la fonction qui tourne en parallèle. Cela risque de provoquer toutes sortes de bizarreries, des chaines remplies bizarrement, d'autres variables qui changent de valeur sans raison... voire un crash.

    Après, j'ai juste regardé le code en diagonale. Je n'ai pas dit qu'il n'y avait pas d'autres bugs qui étaient susceptibles eux aussi de provoquer des bizarreries dans les chaines de caractères. Simplement, le problème que j'expose est déjà un gros soucis à lui seul.

  9. #9
    Membre régulier Avatar de theclem35
    Homme Profil pro
    Technicien Réseaux & Télécommunications
    Inscrit en
    Décembre 2007
    Messages
    148
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Vendée (Pays de la Loire)

    Informations professionnelles :
    Activité : Technicien Réseaux & Télécommunications
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Décembre 2007
    Messages : 148
    Points : 86
    Points
    86
    Par défaut
    Ok maintenant je comprends bien

    C'est genial quelle puissance de réflexion ^^

    j'ai passé les variables en static pour qu'elles restent en mémoire et ca fonctionne nickel

    merci beaucoup pour ton aide j'aimerai bien arriver a autant de reflexion

    Du coup, vu qu'on sort de la fonction de gestion des boutons, mettons que quand le thread se finisse un peu plus tard et qu'il s'est produit une erreur.
    Il renvoie donc -1 mais dans notre fonction de gestion des boutons, or on ne retourne pas dans cette fonction a moins d'appuyer a nouveau sur le bouton

    Dans ce cas comment traiter le code d'erreur en fin de thread si on est deja sorti de la fonction de laquelle il était appellé ?

  10. #10
    Membre régulier Avatar de theclem35
    Homme Profil pro
    Technicien Réseaux & Télécommunications
    Inscrit en
    Décembre 2007
    Messages
    148
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Vendée (Pays de la Loire)

    Informations professionnelles :
    Activité : Technicien Réseaux & Télécommunications
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Décembre 2007
    Messages : 148
    Points : 86
    Points
    86
    Par défaut
    Personne pour me dire comment recuperer la valeur renvoyée par un thread en dehors de la fonction depuis laquelle il a été appellé ?
    (sans passer par les variables globales)

    Peut etre avec une fonction pour recuperer le handle du thread et ensuite d'appeller GetExitCodeThread(hdlThreadServeur, &CodeRetourThread); ???

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [WD15] WaitForMultipleObjects dans un thread bloque mon application
    Par peijnoob dans le forum WinDev
    Réponses: 1
    Dernier message: 22/04/2010, 11h39
  2. fermeture socket dans un thread
    Par adrien1 dans le forum Débuter
    Réponses: 0
    Dernier message: 20/04/2010, 14h45
  3. Probleme de socket dans un thread
    Par nikus dans le forum Threads & Processus
    Réponses: 4
    Dernier message: 25/06/2008, 03h27
  4. problème de socket dans une application win32
    Par deck_bsd dans le forum Windows
    Réponses: 5
    Dernier message: 20/01/2007, 18h32
  5. [Serveur J2EE] Faire tourner un thread dans un serveur d'applications
    Par Pierre-Yves VAROUX dans le forum Java EE
    Réponses: 3
    Dernier message: 13/10/2005, 14h10

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo