SendMessage qui bloque. **new** code minimal qui buggue [WIN32] - C - Programmation
Marsh Posté le 09-10-2003 à 10:05:27
SendMessage est une méthode bloquante (ne sort que quand le message a été traité)
Tu peux effectivement utiliser PostMessage qui n'est pas bloquant.
Marsh Posté le 09-10-2003 à 10:10:12
Kyle_Katarn a écrit : Essaye de faire un PostMessage à la place |
+1
SendMessage est synchrone, tant que le message que tu envoies n'est pas traité, ton programme est bloqué. Pour peu que tu aies bcp de messages en attente, ça le fera pas.
PostMessage est asynchrone, il n'attend pas que le message soit traité.
edit:
Marsh Posté le 09-10-2003 à 10:18:49
De plus, faut faire gaffe avec PostMessage:
Tu passes un pointeur vers ta structure lvi, quand ton message sera traité, cette structure n'existera peut etre plus...
Marsh Posté le 09-10-2003 à 10:25:29
oui mais si je fais un postmessage, le message ne sera alors pas traité ? ou il sera mis a la queue ? Et ca peut bloquer meme si seulement 3 ou 4 message (enfin moins de 20 c sur) sont envoyés.
Marsh Posté le 09-10-2003 à 11:01:32
Bon ca ne fonctionne pas du tout avec PostMessage et ca plante meme (surement a cause du fait que ma structure LVITEM n existe plus en memoire, mais je n ai pas le choix)
De toute facon, si le SendMessage bloque a l infini c est qu il y a un probleme mais je ne vois pas lequel.
Peut etre du a l'appel SendMessage dans un thread ? en tout cas j ai vérifié la valeur du Handle de fenetre, il est correct. Je ne comprends vraiment pas ce qu il se passe. Et vu que je n ai pas le code source de SendMessage (merci ms) je ne peux pas voir quel est le probleme et pourquoi ca boucle.
Marsh Posté le 14-10-2003 à 16:06:33
bon j ai tenté de faire un code minimal qui fait la meme chose et ca plante de la meme facon.
C est tres simple: j'ai une boite de dialogue avec un bouton (check box) et un ListCtrl (MFC)
le button :
lorsqu on appuie sur le bouton , il met une variable a 1 et cree un thread .
lorsqu on réappuie sur le bouton, il met cette meme variable a 0 et attend que le thread stoppe.
le thread :
il boucle sur cette variable, tant qu elle est a un, il insere une ligne dans le listctrl PUIS s endort 500 ms. Lorsqu il sort de la boucle il insere a nouveau une ligne (que je differencie par le texte inséré) et la il bloque sur cette insertion.
Comment ca se fait ? y a t il un mecanisme que j ai pas compris ?
je vous mets egalement le code de cette application minimale.
Code :
|
Marsh Posté le 14-10-2003 à 17:33:53
j'ai pas tout lu (trop de mfc), et je vois rien dans le thread qui peut bloquer indéfiniment, mais essaye d'éviter le "WaitForSingleObject(hSendThread,INFINITE);" et remplace le INFINITE par disons 1 ou 2 sec. ensuite tu testes la valeur de retour : par ex si ca te renvoie WAIT_TIMEOUT (timeout écoulé) bah t'as plus qu'a killer le thread (TerminateThread), mais franchement ca serait bizarre que ca soit le thread qui bloque comme ca...
Marsh Posté le 14-10-2003 à 17:41:04
bah mfc j ai pas trop le choix mais ca change rien , effectivement les 2 fonctions interessantes sont OnOn() et SendThreadFunc() (le reste on s en fout). ET si je vire le WaitSingleObject ca passe (normal vu que j attends pas). Effectivement c est mon thread qui bloque parceque tout simplement , l appel a InsertItem (qui est en fait un sendmessage) bloque. donc thread bloqué -> processus principal egalement bloqué.
Mon réel problème est : pourquoi mon InsertItem(stop) bloque a ce moment la alors que si je le mets en commentaire, AUCUN des autres InsertItem ne bloque.
Je vous mets au défi : essayer de faire une appli minimale (meme sans MFC) qui insere des lignes dans un ListCtrl tous les X millisecondes par l'intermediaire d'un thread, et bien ca bloquera .
Marsh Posté le 14-10-2003 à 17:58:15
moui pourquoi pas... pas grand chose a faire la.
sinon pour resoudre ton pb, tu fais un beau TerminateThread et puis voila...
Marsh Posté le 14-10-2003 à 18:13:15
bon... a priori tu aurais raison, ca bloque sur la derniere insertion, apres la boucle while du thread.
pour infos : proj en win32, en C, et insertion dans une listbox.
vais regarder ca de plus près... y a pas de raison pour que ca marche pas.
Marsh Posté le 14-10-2003 à 18:23:45
je viens de comprendre pourquoi : (attention c'est complexe a expliquer)
apres la mise a 0 de la variable qui permet de dire au thread de se finir, tu fais un WaitForSingleObject. Donc la boucle while du thread se termine, et l'appel a SendMessage s'effectue. Or le WaitForSingleObject (qui est un peu l'équivalent d'un Sleep) se trouve dans la DlgProc, et bloque donc tous les messages en queue, ce qui bloque le SendMessage de la listbox, et donc tu te retrouves dans une position ou le SendMessage du thread attend que le msg soit traité, et ta DlgProc attend que le thread se termine => on appelle ca un deadlock je crois : les 2 threads attendent un évenement de la part de l'autre thread, et sont donc bloqués...
remplacer le dernier SendMessage par un PostMessage résoud la situation.
edit:
en fait remplacer le Send par un Post c'est pas forcèment la bonne solution, pasque bloquer la DlgProc c'est jamais bon. tu devrais donc eviter le WaitForSingleObject, et trouver un autre moyen, selon tes besoins.
En mettant juste la variable a 0 ca suffirait pas ?
Marsh Posté le 14-10-2003 à 18:39:26
Deux suggestions :
Ton code dans ta thread serait du genre :
Code :
|
Marsh Posté le 14-10-2003 à 18:48:15
Ca change pas le pb de la DlgProc bloquée.
ca revient au même de virer le SendMessage (ou le InsertItem dans son cas) situé après le while du thread, pour le mettre apres le WaitForSingleObject de l'évenement du clic de bouton. La DlgProc sera bloquée au max 500 ms (quoique c'est pas critique non plus...)
Marsh Posté le 14-10-2003 à 18:55:03
merci beaucoup , je n avais pas pensé que le WaitForSingleObject bloquait le traitement des messages. Je vais donc essayer de trouver une solution a ce probleme.
eh beh , c est pas facile a détecter ce genre de probleme.
Encore merci de votre aide , ca m'aide beaucoup ... je vous dirai demain si j ai reussi a trouver une autre solution.
edit : konar, ton explication etait tres claire
Marsh Posté le 09-10-2003 à 09:50:14
salut,
j'ai un probleme que je n arrive pas a resoudre. J'ai une fonction qui me permet de logguer dans un ListCtrl ce que je veux. Ma fonction qui insere dans le ListCtrl est la suivante :
cela marche tres bien a 99% du temps. Mais sur un cas bien precis la fonction SendMessage bloque indefiniment.
Ce cas est le suivant :
J'ai un bouton de type ON/OFF , j appuie une fois dessus ca declenche une action, une fois a nouveau ca la stoppe.
- ON : je cree un thread, je mets une variable V a TRUE et celui ci m'envoie a intervalle regulier (200 ms)par le biais d une boucle sur V un caractere sur le port serie, puis un 2eme (20 mn apres le premier). Chaque ecriture sur le port serie est logguée, et ca apparait tres bien dans la fenetre de log.
- OFF : Je mets ma variable V a FALSE ce qui a pour but d arreter la boucle d envoi des caractere, puis envoie un caractere different sur le port (caractere de stop). Sachant que toutes les ecritures sont logguées , je loggue egalement celle ci, le log fichier, memoire fonctionne bien mais des que je loggue dans la fenetre de log mon SendMessage d insertion de ligne bloque. C est aussi simple que ca.
Pendant le ON, je peux envoyer autant de caractere que necessaire, ca ne bloque pas. Mais des que je stoppe ,ca bloque.
Quelqu un aurait il une idee ?
merci
Message édité par xilebo le 16-10-2003 à 13:42:15