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++Builder Discussion :

Multithreading avec TMessage [Système/Fichiers/API]


Sujet :

C++Builder

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre actif
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mars 2012
    Messages
    58
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Indre et Loire (Centre)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Industrie

    Informations forums :
    Inscription : Mars 2012
    Messages : 58
    Par défaut Multithreading avec TMessage
    Bonjour à tous,

    Suite au sujet Utilisation de RawInput, un nouveau problème m'est apparu : Le ressources utilisées par le traitement.

    Je m'explique, dans ma solution de RawInput, ma fonction WMInput vers laquelle sont redirigés tout les messages WM_INPUT tourne donc constamment pour effectuer le traitement lié à mes données de souris.

    Le problème, c'est qu'une fois le traitement activé, je ne peux plus rien faire, l'application est comme "figée" bien que les valeurs indiquées dans mon TEdit se mettent bien à jour.

    J'ai donc fait quelques recherches sur les Threads, j'ai essayé d'intégrer ma fonction de gestionnaire des messages Windows dans ce thread, mais les paramètres de cette fonction étant des TMessages, apparemment ça n'est pas pris.

    Voici mon code pour créér le Thread :

    Unit1.cpp :
    Code C++ : 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
    //---------------------------------------------------------------------------
    #include <stdio.h>
    #include <string.h>
    #include <iostream>
    #include <windows.h>
    #include <winuser.h>
    #include <windef.h>
    #include <vcl.h>
    #pragma hdrstop
    #include "Unit1.h"
    //---------------------------------------------------------------------------
    #pragma package(smart_init)
    #pragma resource "*.dfm"
    TForm1 *Form1;
    RAWINPUTDEVICE Rid[1];
    HRESULT hResult=0;
    POINT cursor;
    static float X = 0;
    static float Y = 0;
    static float cursorX, cursorY;
    static float K = 0;
    HANDLE hThread;
    DWORD ThreadId;
    int DataThread = 1;
    //---------------------------------------------------------------------------
    __fastcall TForm1::TForm1(TComponent* Owner)
    	: TForm(Owner)
    {
     
    }
    //---------------------------------------------------------------------------
    void __fastcall TForm1::Button1Click(TObject *Sender)
    {
    	if(Button1->Caption=="Démarrer")
    	{
    		GetCursorPos(&cursor);
    		cursorX = cursor.x;
    		cursorY = cursor.y;
    		Rid[0].usUsagePage = 1;
    		Rid[0].usUsage = 2;
    		Rid[0].dwFlags = RIDEV_NOLEGACY | RIDEV_INPUTSINK;   // adds HID mouse and also ignores legacy mouse messages
    		Rid[0].hwndTarget = Handle;
    		hResult = RegisterRawInputDevices(Rid, 1, sizeof(Rid[0]));
     
    		if(FAILED(hResult)) ShowMessage("Erreur N°"+GetLastError());
     
    		hThread = CreateThread(NULL, 0, WMInput, &DataThread, 0, &ThreadId);
    		if(hThread==NULL)
    			ExitProcess(DataThread);
     
    		Button1->Caption="Arrêter";
    	}
    	else if(Button1->Caption=="Arrêter")
    	{
    		TerminateThread(hThread, ThreadId); //Stop the Thread
    		Button1->Caption="Démarrer";
        }
    }
    //---------------------------------------------------------------------------
    void __fastcall WMInput(TMessage &Message)
    {
    	UINT dwSize;
     
    	GetRawInputData((HRAWINPUT)Message.LParam, RID_INPUT, NULL, &dwSize,sizeof(RAWINPUTHEADER));
    	LPBYTE lpb = new BYTE[dwSize];
     
    	if (GetRawInputData((HRAWINPUT)Message.LParam, RID_INPUT, lpb, &dwSize,
    		 sizeof(RAWINPUTHEADER)) != dwSize ) {}
     
    	RAWINPUT* raw = (RAWINPUT*)lpb;
    	if (raw->header.dwType == RIM_TYPEMOUSE)
    	{
    		if((int)raw->header.hDevice>65607)
    		{
    			SetCursorPos(cursorX, cursorY);
    			X+= ((raw->data.mouse.lLastX)*2.54)/1000;
    			Y+= ((raw->data.mouse.lLastY)*2.54)/1000;
     
    			K=sqrt((X*X)+(Y*Y));
    			if(X+Y<0)
    				K = -K;
    		}
    		else
    		{
    			GetCursorPos(&cursor);
    			cursorX=cursor.x;
    			cursorY=cursor.y;
    		}
     
    		Form1->Edit1->Text=-K;
    	}
     
    	delete[] lpb;
    }
    //---------------------------------------------------------------------------

    Unit1.h :
    Code C++ : 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
    //---------------------------------------------------------------------------
    #define WM_INPUT 0x00FF
    #ifndef Unit1H
    #define Unit1H
    //---------------------------------------------------------------------------
    #include <System.Classes.hpp>
    #include <Vcl.Controls.hpp>
    #include <Vcl.StdCtrls.hpp>
    #include <Vcl.Forms.hpp>
    //---------------------------------------------------------------------------
    class TForm1 : public TForm
    {
    __published:	// Composants gérés par l'EDI
    	TButton *Button1;
    	TEdit *Edit1;
    	void __fastcall Button1Click(TObject *Sender);
    private:	// Déclarations utilisateur
    public:		// Déclarations utilisateur
    	__fastcall TForm1(TComponent* Owner);
    	void __fastcall WMInput(TMessage &Message);
    	BEGIN_MESSAGE_MAP
    		MESSAGE_HANDLER(WM_INPUT, TMessage, WMInput)
    	END_MESSAGE_MAP(TForm)
    };
    //---------------------------------------------------------------------------
    extern PACKAGE TForm1 *Form1;
    //---------------------------------------------------------------------------
    #endif


    A la compilation, j'ai cette erreur-ci qui surgit du fin fond des abysses :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    [BCC32 Erreur] Unit1.cpp(47): E2034 Impossible de convertir 'unsigned long (__stdcall * (_closure )(void *))(void *)' en 'unsigned long (__stdcall *)(void *)'
    [BCC32 Erreur] Unit1.cpp(47): E2342 Mauvaise correspondance de type dans le paramètre 'lpStartAddress' ('unsigned long (__stdcall *)(void *)' désiré, 'void' obtenu)

    Suite à ceci, j'en conclu donc qu'avec mon code, il m'est impossible de passer directement ma fonction WMINPUT dans le nouveau Thread, ma question est donc, comment faire pour effectuer cette fonction dans un Thread séparé du programme principal, afin de ne pas "figer" celui-ci sachant que la fonction est comme une boucle infinie ?

    Cordialement.

  2. #2
    Expert éminent
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    14 081
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 14 081
    Par défaut
    SetCursorPos !
    Tu modifie la souris pendant le traitement, risque de réentrance !

    Ajoute dans ton WMInput, un élément à chaque fois, ligne de code par ligne de code, tu détermineras ce qui provoque la boucle !


    Tu n'as toujours pas compris que la fonction WMInput est appelé par la boucle Application->Run() chargé de lire la file des messages Windows, je pensais te l'avoir expliqué

    Comment veux tu que le thread devine le TMessage qu'il doit passer en paramètre, un ordinateur n'est pas prescient !

    Tu peux tenter un TThread (classe RTL encapsulant les thread, sous C++Builder autant utiliser la RTL puisque c'est son principal intérêt)

    Dans le TThread.Execute, tu fais une boucle (Terminated permet son arrêt) et dans cette boucle tu fais appel à WaitMessage\PeekMessage (voir ce code), tu filtre sur le WM_INPUT

    une autre solution, serait de laisser WMInput dans l'état, couplé un TEvent et un TThread.
    WMInput puslerait le TEvent
    le TThread lui se chargerait de GetRawInputData lors de l'éveil de TEvent
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  3. #3
    Membre actif
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mars 2012
    Messages
    58
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Indre et Loire (Centre)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Industrie

    Informations forums :
    Inscription : Mars 2012
    Messages : 58
    Par défaut
    La souris n'est pas modifiée, je force simplement la position du curseur à sa position précédente si la souris de mesure a détecté un déplacement.
    Les données que je reçois sont uniquement les données envoyées par la souris (enfin d'après ce que j'ai compris).

    Certes cette méthode est un peu crade, mais pour ce que je cherche à faire, ça marche pas mal, et j'ai rien trouvé d'autre pour que ma deuxième souris ne fasse pas bouger le curseur.

    Bref, j'ai regardé un peu comment ça tournait avec l'objet TThread de C++Builder, et j'ai eu l'impression que le Thread ne passait jamais dans le BEGIN_MESSAGE_MAP.

    Du coup, suite à tes propositions, selon toi je devrais mettre dans l'Execute() du Thread :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    PeekMessage(lpMsg, Form1->Handle, WM_INPUT, WM_INPUT, PM_REMOVE);
    Si c'est le cas, en premier paramètre (lpMsg) je dois mettre un lien avec mon traitement de message ?

    J'en profite pour demander un petit truc, toujours en liaison avec RawInput, est-ce que je peux effectuer mon RegisterRawInputDevices sur ma Form1 (en cliquant sur le bouton Démarrer), mais effectuer le traitement et la gestion des messages de ma souris sur le Thread ?

    Parce qu'après plusieurs essais, même en mettant un simple ShowMessage dans mon Thread, le programme reste figé après un click sur le bouton (et donc un RegisterRawInputDevices), alors que les fonctions s’exécutent bien.

  4. #4
    Membre actif
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mars 2012
    Messages
    58
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Indre et Loire (Centre)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Industrie

    Informations forums :
    Inscription : Mars 2012
    Messages : 58
    Par défaut
    Bon ben finalement j'ai réussi à faire fonctionner le tout, c'était la ligne Rid[0].dwFlags = NO_LEGACY; qui faisait figer l'API.

    Merci quand même d'avoir répondu.

    Unit1.cpp :
    Code C++ : 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
    //---------------------------------------------------------------------------
    #include <stdio.h>
    #include <string.h>
    #include <iostream>
    #include <windows.h>
    #include <winuser.h>
    #include <windef.h>
    #include <vcl.h>
    #pragma hdrstop
    #include "Unit1.h"
    #include "Unit2.h"
    //---------------------------------------------------------------------------
    #pragma package(smart_init)
    #pragma resource "*.dfm"
    TForm1 *Form1;
    ThreadSouris *Thread;
    //---------------------------------------------------------------------------
    __fastcall TForm1::TForm1(TComponent* Owner)
    	: TForm(Owner)
    {
    }
    //---------------------------------------------------------------------------
    void __fastcall TForm1::Button1Click(TObject *Sender)
    {
    	if(Button1->Caption=="Démarrer")
    	{
    		Thread = new ThreadSouris(true);
    		Thread->Priority=tpNormal;
    		Thread->Start();
    		Button1->Caption="Arrêter";
    	}
    	else if(Button1->Caption=="Arrêter")
    	{
    		Thread->Terminate();
    		Button1->Caption="Démarrer";
    	}
    }
    //---------------------------------------------------------------------------

    Unit1.h :
    Code C++ : 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
    //---------------------------------------------------------------------------
    #define WM_INPUT 0x00FF
    #ifndef Unit1H
    #define Unit1H
    //---------------------------------------------------------------------------
    #include <System.Classes.hpp>
    #include <Vcl.Controls.hpp>
    #include <Vcl.StdCtrls.hpp>
    #include <Vcl.Forms.hpp>
    //---------------------------------------------------------------------------
    class TForm1 : public TForm
    {
    __published:	// Composants gérés par l'EDI
    	TButton *Button1;
    	TEdit *Edit1;
    	void __fastcall Button1Click(TObject *Sender);
    private:	// Déclarations utilisateur
    public:		// Déclarations utilisateur
    	__fastcall TForm1(TComponent* Owner);
    	void __fastcall WMInput(TMessage &Message);
    	BEGIN_MESSAGE_MAP
    		MESSAGE_HANDLER(WM_INPUT, TMessage, WMInput)
    	END_MESSAGE_MAP(TForm)
    };
    //---------------------------------------------------------------------------
    extern PACKAGE TForm1 *Form1;
    //---------------------------------------------------------------------------
    #endif

    Unit2.cpp :
    Code C++ : 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
    //---------------------------------------------------------------------------
    #include <stdio.h>
    #include <string.h>
    #include <iostream>
    #include <windows.h>
    #include <winuser.h>
    #include <windef.h>
    #include <vcl.h>
    #pragma hdrstop
    #include "Unit1.h"
    #include "Unit2.h"
    #pragma package(smart_init)
    //---------------------------------------------------------------------------
     
    //   Important : Les méthodes et les propriétés des objets de la VCL peuvent seulement être
    //   utilisées dans une méthode appelée avec Synchronize, par exemple :
    //
    //      Synchronize(&UpdateCaption);
    //
    //   où UpdateCaption pourrait ressembler à :
    //
    //      void __fastcall ThreadSouris::UpdateCaption()
    //      {
    //        Form1->Caption = "Mis à jour dans un thread";
    //      }
    //---------------------------------------------------------------------------
    static int reg=0;
    RAWINPUTDEVICE Rid[1];
    HRESULT hResult=0;
    POINT cursor;
    static float X = 0;
    static float Y = 0;
    static float cursorX, cursorY;
    static float K = 0;
    //---------------------------------------------------------------------------
    __fastcall ThreadSouris::ThreadSouris(bool CreateSuspended)
    	: TThread(CreateSuspended)
    {
    }
    //---------------------------------------------------------------------------
    void __fastcall ThreadSouris::Execute()
    {
    	//---- Placer le code du thread ici ----
    	while(Form1->Button1->Caption=="Arrêter")
    	{
    		if(reg==0)
    		{
    			GetCursorPos(&cursor);
    			cursorX = cursor.x;
    			cursorY = cursor.y;
    			Rid[0].usUsagePage = 1;
    			Rid[0].usUsage = 2;
    			Rid[0].dwFlags = 0;   // adds HID mouse and also ignores legacy mouse messages
    			Rid[0].hwndTarget = Form1->Handle;
    			hResult = RegisterRawInputDevices(Rid, 1, sizeof(Rid[0]));
     
    			if(FAILED(hResult)) ShowMessage("Erreur N°"+GetLastError());
    			reg=1;
    		}
    	}
    }
    //---------------------------------------------------------------------------
    void __fastcall TForm1::WMInput(TMessage &Message)
    {
    	UINT dwSize;
     
    	GetRawInputData((HRAWINPUT)Message.LParam, RID_INPUT, NULL, &dwSize,sizeof(RAWINPUTHEADER));
    	LPBYTE lpb = new BYTE[dwSize];
     
    	if (GetRawInputData((HRAWINPUT)Message.LParam, RID_INPUT, lpb, &dwSize,
    		 sizeof(RAWINPUTHEADER)) != dwSize ) {}
     
    	RAWINPUT* raw = (RAWINPUT*)lpb;
    	if (raw->header.dwType == RIM_TYPEMOUSE)
    	{
    		if((int)raw->header.hDevice>65607)
    		{
    			SetCursorPos(cursorX, cursorY);
    			X+= ((raw->data.mouse.lLastX)*2.54)/1000;
    			Y+= ((raw->data.mouse.lLastY)*2.54)/1000;
     
    			K=sqrt((X*X)+(Y*Y));
    			if(X+Y<0)
    				K = -K;
    		}
    		else
    		{
    			GetCursorPos(&cursor);
    			cursorX=cursor.x;
    			cursorY=cursor.y;
    		}
     
    		Form1->Edit1->Text=-K;
    	}
     
    	delete[] lpb;
    }
    //---------------------------------------------------------------------------

    Unit2.h :
    Code C++ : 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
    //---------------------------------------------------------------------------
    #define WM_INPUT 0x00FF
    #ifndef Unit2H
    #define Unit2H
    //---------------------------------------------------------------------------
    #include <System.Classes.hpp>
    //---------------------------------------------------------------------------
    class ThreadSouris : public TThread
    {
    private:
    protected:
    	void __fastcall Execute();
    public:
    	__fastcall ThreadSouris(bool CreateSuspended);
    	void __fastcall WMInput(TMessage &Message);
    };
    //---------------------------------------------------------------------------
    #endif

  5. #5
    Expert éminent
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    14 081
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 14 081
    Par défaut
    Si c'est RIDEV_NOLEGACY qui bloquait
    Du coup, le thread n'est plus utile ?
    J'ai testé, cela fonctionne sans thread avec le 0 dans dwFlags

    je crois que le RIDEV_NOLEGACY, comme le mentionnait désactive la souris et donc ton application ne reçoit plus les WM_MOUSE qu'il faut Dispatcher soit-même depuis WM_INPUT, je crois que dans l'un des sujet que tu as ouvert, c'était minnesota ou AndNotOr qui l'avait expliqué

    Ce n'était pas bloqué mais juste qu'il ne réagit pas, car le clavier fonctionne lui sans aucun problème, le tab pour naviguer entre Edit1 et Button1 par exemple !



    Quelque remarques sur le code en lui même

    Pour ma part, j'utilise VCL_MESSAGE_HANDLER au lieu du MESSAGE_HANDLER
    Pourquoi WMInput n'est pas une méthode de TForm1 ?
    Cela serait plus pratique !

    J'ai relu ton code, les variables globales, c'est dégueux, mets en local ou en membre privé de TForm1 !
    Pourquoi des variables static ? c'est surtout utile dans une fonction pour avoir une sorte de variable locale permanente
    Bon, je suppose que c'est juste un code de test, utiliser le Caption dans un test, ce n'est pas top !


    Pas de ShowMessage, de TForm ou autre élément VCL dans un Thread sans utiliser de Synchronize, c'est à tes risques et périls !
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  6. #6
    Membre actif
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mars 2012
    Messages
    58
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Indre et Loire (Centre)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Industrie

    Informations forums :
    Inscription : Mars 2012
    Messages : 58
    Par défaut
    Oui là c'était juste un test pour vraiment avoir un truc qui marche avant de l'intégrer à mon programme principal, je soignerai bien comme il faut le code en temps voulu, j'ai encore pas mal de temps devant moi avant de terminer.

    Du coup j'ai quand même gardé le Thread, j'ai pas essayé avec le dwFlags à 0 sans le Thread, étant donné la nature gourmande du traitement principal que j'ai à faire, ça fera pas de mal de rester comme cela.

    Ouais sur le moment j'avais pas compris ça comme ça, j'ai bien saisi le concept tout à l'heure en relisant bien le post sur les deux claviers en Delphi justement. Et j'arrivais également à naviguer avec tab mais j'avais pas fait le rapprochement.

    Pour le WMInput, il est bien déclaré dans TForm1.

    Il y a une réelle différence entre VCL_MESSAGE_HANDLER et MESSAGE_HANDLER ?

    Ça risque quoi si je n'utilise pas Synchronize au juste ?

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

Discussions similaires

  1. Multithreading avec section critique ?
    Par Cokate dans le forum C#
    Réponses: 8
    Dernier message: 25/08/2008, 16h05
  2. Lancer une application multithread avec msdos
    Par SpIrIt505050 dans le forum Débuter avec Java
    Réponses: 3
    Dernier message: 11/06/2008, 19h47
  3. Multithread avec partage de ressources et join
    Par Razgriz dans le forum Langage
    Réponses: 4
    Dernier message: 09/05/2008, 10h41
  4. Multithreading avec Visual Basic pour Access
    Par NoViceDel dans le forum VBA Access
    Réponses: 2
    Dernier message: 12/10/2006, 21h18

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