Tâche en continu dans une appli WIN32 [Résolu]

Signaler
Messages postés
8
Date d'inscription
mardi 17 février 2004
Statut
Membre
Dernière intervention
22 février 2013
-
Messages postés
1910
Date d'inscription
vendredi 18 juin 2004
Statut
Modérateur
Dernière intervention
14 novembre 2014
-
Bonjour,

Je suis en train de m'initier à la programmation d'une application Win32 en langage C. Voilà le fonctionnement de la partie qui me pose problème:

Lorsque l'utilisateur clique sur un bouton, je pilote une sonde brancher sur l'USB qui envoie une commande et récupère une donnée. En fonctionnement standard, un clic de l'utilisateur ça fonctionnement ça problème.

Je voudrais faire un autre bouton qui active une fonctionnement SCAN, cad que j'émets la commande et reçois en continue la donnée avc mise à jour de la donnée dans un Edit.

Et c'est cette partie que je ne sais pas gérer, je ne sais pas où positionner mon code pour que ça n'empêche pas de prendre en compte un clic de l'utilisateur pour stopper le scan. Si je le positionne dans le "case" des messages reçus par la fenêtre, ma donnée se met à jour uniquement quand ma fenêtre à le focus (souris devant la fenêtre). Je foudrais qu'elle cela fonctionne même si je clique sur un autre programme du même genre qu'une tâche de fond.

Je ne sais pas si vous allez comprendre mon problème, mais merci d'avance


@mitié d'internaute
FRED

7 réponses

Messages postés
14884
Date d'inscription
lundi 11 juillet 2005
Statut
Modérateur
Dernière intervention
30 novembre 2020
93
Hello,
Il te faut lancer un thread dédié à la récupération des messages de ta sonde:
- dès qu'une donnée est reçue, ton thread envoie un message (SendMessage) à ta fenêtre principale pour maj
- dès que le user clique sur le bouton stop, ça envoie un message à ton thread qui arrête de récupérer des infos

Ou bien, tu passes par un timer qui va vérifier les données à chaque "tick"

@+
Buno
----------------------------------------
L'urgent est fait, l'impossible est en cours. Pour les miracles, prévoir un délai...
Messages postés
14884
Date d'inscription
lundi 11 juillet 2005
Statut
Modérateur
Dernière intervention
30 novembre 2020
93
Tu isoles dans une fonction la récupération des données depuis le scan.
Dans le cas du thread, cette fonction contient quelque chose te permettant de boucler à l'infini. Par exemple
while (1)
{
...
}

Tu crée le thread via CreateThread()
A l'appui sur le bouton Stop, il suffit de killer le thread (voir CloseHandle()).

Pour le timer, en début de prog, tu fais un SetTimer(). Dans ta boucle de message, tu capture le message WM_TIMER via le switch et tu peux appeler ta fonction de récup de données. Sur l'action d'appui sur Stop, tu fais un KillTimer()

Tu devrais pouvoir trouver des exemples bien fait sur ce site.

@+
Buno
----------------------------------------
L'urgent est fait, l'impossible est en cours. Pour les miracles, prévoir un délai...
Messages postés
1910
Date d'inscription
vendredi 18 juin 2004
Statut
Modérateur
Dernière intervention
14 novembre 2014
12
Salut,
Juste une remarque pour buno à propos de CloseHandle(). Cette fonction ne provoque pas l'arrêt du thread. Elle ne fait que fermer son handle quand il n'est plus utilisé. Un thread se termine de lui même quand il atteint un "return" dans sa fonction. Pour terminer proprement un thread on peut utiliser une variable globale qu'on doit tester à chaque itération de la boucle infinie pour décider d'en sortir ou non. Cette variable jouera le rôle d'un flag à positionner suite au clic sur le bouton "Stop" par exemple. Une autre solution consiste à mettre une boucle de message dans le code de la fonction du thread. Ainsi, ce dernier recevra, entre autres, un message provoquant la sortie de cette boucle. On utilise PostThreadMessage() pour envoyer un message à un thread. Les deux méthodes permettent au thread de se nettoyer, si besoin est, avant de se terminer. TerminateThread() est à éviter.
Messages postés
8
Date d'inscription
mardi 17 février 2004
Statut
Membre
Dernière intervention
22 février 2013

Bonjour Bruno et merci de ta réponse,
tu peux m'aiguiller vers un exemple ou un tutoriel qui explique un peu l'utilisation des threads, je suis un novice en la matière.

Le principe du timer en détail c'est peut être plus simple, ça donne quoi dans les grandes lignes ?

merci encore
Messages postés
14884
Date d'inscription
lundi 11 juillet 2005
Statut
Modérateur
Dernière intervention
30 novembre 2020
93
Ah oui, oups...
Merci de la précision.

@+
Buno
----------------------------------------
L'urgent est fait, l'impossible est en cours. Pour les miracles, prévoir un délai...
Messages postés
21042
Date d'inscription
jeudi 23 janvier 2003
Statut
Modérateur
Dernière intervention
21 août 2019
24
Les Event sont également très pratiques dans ce genre de situation.
Je te donne un morceau de code d'un de mes progs, le thread primaire fait tourner en simultané plusieurs threads auxiliaires.

typedef struct _CPRSSAUX {
LPBNCMPRSS pCMPRS; // +0
HANDLE hevParent; // +8
HANDLE hevWait; // +16
HANDLE hthrd; // +24
BYTE bEnd; // +32
BYTE err; // +33, 1 LECTURE, 2 COMPRESSION
BYTE work; // +34, 1 doit compresser, 0 rien
BYTE dummy[5]; // +35
} CPRSSAUX, *LPCPRSSAUX; // sizeof = 40

DWORD WINAPI CmprsAux(LPVOID pprm)
{
LPCPRSSAUX paux = (LPCPRSSAUX) pprm;
nextDataProc:
WaitForSingleObject(paux->hevWait, INFINITE);
paux->err = 0;
ResetEvent(paux->hevWait);
if(paux->bEnd) goto notifPARENT;
if(!paux->work) goto notifPARENT;
paux->err = (BYTE) bnCompressEx(paux->pCMPRS);
notifPARENT:
SetEvent(paux->hevParent);
if(!paux->bEnd) goto nextDataProc;
return 0;
}

Dans la fonction de thread, on voit que le thread ne fera jamais de boucle éternelle. A chaque tour il notifie le parent de l'état de son travail et ne se remet en position de départ que si le parnet l'indique, sinon il sort proprement.
Les boucles éternelles utilisent inutilement les CPUs, c'est à éviter comme la peste.

ciao...
BruNews, MVP VC++
Messages postés
1910
Date d'inscription
vendredi 18 juin 2004
Statut
Modérateur
Dernière intervention
14 novembre 2014
12
Oui tout à fait BruNews. J'ai évité de parler de l'utilisation des Events et autres objets Windows pour ne pas charger le post. Personnellement, je préfère utiliser des boucles de messages dans les threads. Ceci permet une communication parfaite avec le thread primaire. Chaque thread sait où en est arrivé l'autre et agit en conséquence en échangeant des messages personnalisés. Je trouve même que c'est plus direct. Ainsi, le thread peut exécuter différentes tâches selon le message reçu et informe son appelant du résultat du traitement. Quelques appels PostThreadMessage() remplaceraient avantageusement les CreateEvent(), SetEvent(), ResetEvent() et WaitForSingleObject(). Enfin c'est ce que je pense à moins qu'il y ait une vraie raison de toujours préférer ces fonctions pour la communication entre threads.
Les boucles infinies bouffent le temps CPU si elles ne contiennent pas de fonction bloquante. Mais parfois on est obligé d'utiliser ces boucles pour finir un certain traitement le plus vite possible même en chargeant à fond les CPUs.