Passer des arguments à un Thread & framework 2.0

Signaler
Messages postés
28
Date d'inscription
mercredi 22 décembre 2004
Statut
Membre
Dernière intervention
29 mai 2007
-
Messages postés
28
Date d'inscription
mercredi 22 décembre 2004
Statut
Membre
Dernière intervention
29 mai 2007
-
Salut,

Je dois faire une interface graphique qui permet de s'échanger des fichiers xml.
Sans trop rentrer dans les détails je dois faire 2 serveur UDP écoutant 2 ports différents, 1 client UDPBroadast et 1 serveur TCP multithreadé.
Le problème c'est que je suis une quiche en c++.
Je n'en suis qu'au début et je m'attaque au deux serveur UDP. J'ai pensé faire un thread mais je ne sais pas comment lui passer des arguments (en l'occurence le numéro du port qu'il doit écouter).
De plus au moment où je souhaite récupérer le nombre de bytes reçus en exécutant :
count = socket_udp->ReceiveFrom(buffer_reception,_port_distant);

Ma fenetre se gèle. En mode débug je ne remarque rien de particulier.
Help!!!!

Merci d'avance.

7 réponses

Messages postés
966
Date d'inscription
samedi 3 avril 2004
Statut
Membre
Dernière intervention
4 mars 2010
4
Pour le thread, tu utilises la fonction CreateThread : l'argument lpParameter est un pointeur vers une structure contenant les arguments que tu souhaites passer, ou bien directement un pointeur sur une donnée (le numéro du port par exemple).
Messages postés
28
Date d'inscription
mercredi 22 décembre 2004
Statut
Membre
Dernière intervention
29 mai 2007

Merci Juju, ça marche nikel pour le passage d'argument. Par contre g toujours ce problème de fenetre figée.
Voici une partie de mon code. Si quelqu'un comprend ce qui se passe...

try {
                    // On construit la socket.
                    socket_udp = gcnew System::Net::Sockets::Socket(
                        System::Net::Sockets::AddressFamily::InterNetwork,
                        System::Net::Sockets::SocketType::Dgram,
                        System::Net::Sockets::ProtocolType::Udp);

                    adresse_locale = Net::IPAddress::Parse("127.0.0.1");
                    port_local   = gcnew System::Net::IPEndPoint(adresse_locale, port);
                    _port_distant = gcnew System::Net::IPEndPoint(adresse_locale, port); 
                    socket_udp->Bind(port_local);

                    // On alloue le buffer de réception
                    buffer_reception = gcnew array<System::Byte>(10000);
                    while(1) {
                        this->labelVortex->Text="Vortex ouvert";
                        count = socket_udp->ReceiveFrom(buffer_reception,_port_distant);

                        port_distant = dynamic_cast<System::Net::IPEndPoint^>(_port_distant);

                        // Le buffer de réception contient quelque chose du genre:
                        // 20004\nMon message
                        // Dont il faut extraire, de la suite '2' '0' '0' '0' '4' 
                        // la valeur entière 20004.
                        mem_stream = gcnew System::IO::MemoryStream(buffer_reception,0,count);
                        parser = gcnew System::IO::StreamReader(mem_stream); // Lit de l'ascii
                        message = parser->ReadLine();      // Lit "20004\n" et vaut "20004"
                        // Là, on ReadLine a lu tout le stream (???) et
                        // mem_stream->get_Position() retourne la valeur 11
                        // Pour un message 20004\nHello (qui a 11 caractères).
                        // Donc je dois recalculer la position dans mon stream à la main...
                        port_reponse = System::Int32::Parse(message);
                        pos = message->Length + 1;
                        System::Console::WriteLine(                            "Port reponse {0}, pos {1}",
                            System::Convert::ToString(port_reponse),
                            System::Convert::ToString(pos));
                        message = System::Text::Encoding::ASCII->GetString(
                            buffer_reception,pos, count);
                        System::Console::WriteLine("Recu : ");
                        System::Console::Write("  Message : ");
                        System::Console::WriteLine(message);
                        System::Console::WriteLine("       de : {0}",port_distant->Address);


En rouge la ligne qui gèle tout. Voilà si quelqu'un comprend pourkoi ça marche pas ce serait cool.
Messages postés
28
Date d'inscription
mercredi 22 décembre 2004
Statut
Membre
Dernière intervention
29 mai 2007

J'ai trouvé d'où venait le problème mais je ne sais pas comment le résoudre.
Quand mon thread UDPserveur s'exécute, il doit mettre à jour certains controles sur ma windowsform. Donc dans la méthode UDPServeur avec laquelle j'appelle mon thread, j'ai mis un :

if (this->labelVortex->InvokeRequired)
            {
                array<Object^>^ toto = {obj};
                this->Invoke(gcnew MaMethode(this, &Fenetre_principale::UDPServeur), toto );
             }
else{...le vrai corps de la fonction...}

Le Invoke a apparement pour effet d'annuler l'intéret du thread puisqu'après ma fenetre se fige au moment d'aborder ma boucle while(true) (voir message précédant).
Je ne sais pas comment faire. Mon serveur doit passer des messages à ma windowsForm et doit tourner en boucle alors je suis coincé.
Please help!!!
Messages postés
475
Date d'inscription
jeudi 19 juin 2003
Statut
Membre
Dernière intervention
3 novembre 2008

juste comme ça, y a pas de BeginInvoke() ?

[:D] @++
Messages postés
28
Date d'inscription
mercredi 22 décembre 2004
Statut
Membre
Dernière intervention
29 mai 2007

Quelle est la différence entre invoke et beginInvoke?

Sinon j'ai trouvé un moyen peu élégant (mais bon ça fonctionne) de résoudre mon problème.
En fait j'ai crée des fonctions spécifiques pour chaque control de ma windowsForm que je veux modifier et j'apelle ces fonctions quand j'en ai besoin. Je m'explique:

monThread :
void monThread(Object^ obj){
                                              ....................
                                              while(true){
                                                               array<Object^>^ toto = {this->labelVortex,"Vortex  ouvert"};
                                                               this->Invoke(upControl, toto);
                                                               ........................
                                              }
}

upControl:
void UpdateControl(Control^ cont, String^ s){
             cont->Text = s;
}

Je sais c'est un peu moche mais j'ai pas trouvé mieux pour l'instant.
Si quelqu'un a une idée...
Messages postés
475
Date d'inscription
jeudi 19 juin 2003
Statut
Membre
Dernière intervention
3 novembre 2008

Salut, je ne connais rien en C++/CLI.
Mais en .net en général, BeginInvoke invoke ton contrôle d'une manière asynchrome (qui ne bloque pas ton thread).
Ca revient en plus élégant à ce que t'as fait, c'est à dire créer un nouveau thread pour chaque invoke.
Regarde du côté de MSDN la-dessus. Sur CodeProject, un article en parle http://www.codeproject.com/csharp/begininvoke.asp

Bonne chance

[:D] @++
Messages postés
28
Date d'inscription
mercredi 22 décembre 2004
Statut
Membre
Dernière intervention
29 mai 2007

J'ai essayé avec BeginInvoke et j'ai pas eu de meilleurs résultats.
Finalament je pense que je vais me contenter de ma solution un peu sale.
Merci en tout cas ;)