OVH Cloud OVH Cloud

CreateThread

12 réponses
Avatar
Jean-François GAZET
Bonjour,

Dans une applie Win32, je dois appeler une fonction search() qui peut
prendre une 30taine de secondes et qui contient une boucle infinie stoppée
par une variable globale. Si j'appelle cette fonction search() tel quel,
toute l'appli est gelée et ne répond plus. J'utilise alors :

DWORD thread1;
hThread1=CreateThread(
NULL, // pointer to thread security attributes
0, // initial thread stack size, in bytes
(unsigned long (__stdcall *)(void *))search,
NULL, // argument for new thread
0, // creation flags
&thread1 // pointer to returned thread identifier
);

Mais dans ce cas, il semble que la variable globale censée stopper la
recherche n'ait plus d'effet. Je suppose que le thread est un processus
parallèle et qui démarre avec une copie de cette variable globale. Comment
stopper la recherche avec cette variable globale ?
L'autre problème, qui doit être identique est que si je clique sur la croix
pour fermer la fenêtre pendant une recherche, l'appli quitte seulement quand
le thread est terminé.

Merci de votre aide.

10 réponses

1 2
Avatar
amerio
Dans une applie Win32, je dois appeler une fonction search() qui peut
prendre une 30taine de secondes et qui contient une boucle infinie stoppée
par une variable globale. Si j'appelle cette fonction search() tel quel,
toute l'appli est gelée et ne répond plus. J'utilise alors :

DWORD thread1;
hThread1=CreateThread(
NULL, // pointer to thread security attributes
0, // initial thread stack size, in bytes
(unsigned long (__stdcall *)(void *))search,
NULL, // argument for new thread
0, // creation flags
&thread1 // pointer to returned thread identifier
);

Mais dans ce cas, il semble que la variable globale censée stopper la
recherche n'ait plus d'effet. Je suppose que le thread est un processus
parallèle et qui démarre avec une copie de cette variable globale. Comment
stopper la recherche avec cette variable globale ?
L'autre problème, qui doit être identique est que si je clique sur la croix
pour fermer la fenêtre pendant une recherche, l'appli quitte seulement quand
le thread est terminé.


Tu as surement un pb lié à une optim du compilateur.
Il "cache" ta variable globale, car il détecte que ton thread ne la modifie pas (il ne
fait que la lire)
Donc qd tu testes sa valeur, elle ne change jamais (en fait, le code généré ne teste plus
la variable mais sa valeur "cachée").
-> Utilise "volatile"

Je te conseille le lien suivant :
http://www.cuj.com/documents/sy98/cujcexp1902alexandr/

Avatar
James Kanze
Fabien LE LEZ writes:

|> On Sat, 30 Aug 2003 20:27:19 +0200, "Jean-François GAZET"
|> wrote:

|> >Dans une applie Win32

|> Dans ce cas, fr.comp.os.ms-windows.programmation sera sans doute
|> plus adapté. La programmation multithread est un domaine à
|> part entière (qui mérite un bon bouquin à lui tout seul),
|> et dont le langage C++ ne parle pas.

Il y en a des bouquins. Le meilleur que je connais, c'est
« Programming with Posix Threads », par David Butenhof. Même
pour un programmeur Windows, beaucoup de ce qu'il a à dire vaut (mais
évidemment, les noms des fonctions de l'API changent).

|> >, je dois appeler une fonction search() qui peut prendre une
|> >30taine de secondes et qui contient une boucle infinie stoppée
|> >par une variable globale.

|> Variable globale ? Dangereux, ça... ou plus exactement, ça
|> risque de limiter tes possibilités, sans compter le risque qu'un
|> bout de code indépendant y touche par inadvertance.

Disons que c'est une des possibilités pour ce qu'il veut faire. En
revanche, il ne doit pas être question d'y accéder sans des mutex.

Avec des threads Posix, il y a une possibilité de canceler un thread.
Je serais très étonné que Windows n'a pas cette possibilité
aussi.

|> >Je suppose que le thread est un processus parallèle et qui
|> >démarre avec une copie de cette variable globale.

|> Non, la mémoire d'un processus est partagée entre tous les
|> threads.

Non seulement la mémoire, mais toutes les ressources du processus.
C'est la définition même d'un thread.

|> Ce qui oblige à user de pas mal de protections (mutex, critical
|> section) quand deux threads risquent d'accéder à la même
|> variable au même moment...

Quand deux threads risquent d'accéder au même objet,
indépendamment du même moment ou pas.

|> >Comment stopper la recherche avec cette variable globale ?

|> Logiquement, ta solution devrait fonctionner... Mais lis bien la doc
|> (par exemple, il ne faut pas utiliser CreateThread sous Borland
|> C++), ou demande sur fr.comp.os.ms-windows.programmation.

A priori, si la variable est écrite dans un thread, sans
précaution, il n'y a aucune raison pour que l'autre thread voir la
nouvelle valeur, au moins qu'on a pris les précautions réquises.

|> >L'autre problème, qui doit être identique est que si je
|> >clique sur la croix pour fermer la fenêtre pendant une
|> >recherche, l'appli quitte seulement quand le thread est terminé.

|> Normal : un processus se termine quand plus aucun thread ne tourne.

Un process se termine quand on retourne de main, ou quand on appelle
exit. Selon la norme C++, en tout cas, et aussi dans le cas des threads
Posix. Toujours un Posix, un processus se termine aussi lors que tous
les threads sont terminés (par exemple, si on a terminé main en
appelant pthread_exit, à la place d'exit).

En général, en C++, la façon préférable à terminer le
processus, c'est de retourner de main. Ceci assure que tous les
destructeurs des variables locales sont appelées. Dans un contexte
multi-thread, la solution préférée est de s'arranger à ce
que tous les threads se terminent, puis faire un join sur chacun d'eux
en main, puis retourner du main. Mais c'est loin d'être une règle
absolue.

--
James Kanze mailto:
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France +33 1 41 89 80 93
Avatar
James Kanze
"amerio" writes:

|> -> Utilise "volatile"

Volatile n'apporte aucune garantie supplémentaire dans ce cas, au
moins que la documentation du compilateur dit autrement. Il se peut, par
exemple, que le code fonctionne avec volatile dans un contexte
mono-processeur, mais non multi-processeur.

--
James Kanze mailto:
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France +33 1 41 89 80 93
Avatar
amerio
|> -> Utilise "volatile"

Volatile n'apporte aucune garantie supplémentaire dans ce cas, au
moins que la documentation du compilateur dit autrement. Il se peut, par
exemple, que le code fonctionne avec volatile dans un contexte
mono-processeur, mais non multi-processeur.


Oui, en fait, volatil garantit simplement que la variable ne sera pas lu depuis le cache,
mais directement depuis la memoire.
Mais en effet, ca n'interdit pas que deux autres threads puissent ecrire dedans en meme
temps, et qu'on relise une valeur aberrante.
Dans son cas précis, il precise pourtant qu'il n'y a que DEUX threads en tout : un qui
ecrit, un qui lit. Donc meme en multiprocesseur, il n'aura pas de pb avec volatil (ou bien
me trompe-je ?).
Mais tu as raison de souligné le pb : la seule vrai solution serait un mutex, mais dans
son cas, cela me parraissait un peu "lourd"...

Avatar
M.B.
Pour la programmation avancee sous Windows, une autre
'BON' bouquin :

"Developper des applications sous Windows"
Jeffrey Richter
Microsoft Press

(process, thread, semaphore, mutex, etc ...)

MB

"James Kanze" a écrit dans le message news:


Il y en a des bouquins. Le meilleur que je connais, c'est
« Programming with Posix Threads », par David Butenhof. Même
pour un programmeur Windows, beaucoup de ce qu'il a à dire vaut (mais
évidemment, les noms des fonctions de l'API changent).



Avatar
Patrick Mézard
"amerio" a écrit dans le message de
news:0Nr4b.30395$
|> -> Utilise "volatile"

Volatile n'apporte aucune garantie supplémentaire dans ce cas, au
moins que la documentation du compilateur dit autrement. Il se peut, par
exemple, que le code fonctionne avec volatile dans un contexte
mono-processeur, mais non multi-processeur.


Oui, en fait, volatil garantit simplement que la variable ne sera pas lu
depuis le cache,

mais directement depuis la memoire.
Mais en effet, ca n'interdit pas que deux autres threads puissent ecrire
dedans en meme

temps, et qu'on relise une valeur aberrante.
Dans son cas précis, il precise pourtant qu'il n'y a que DEUX threads en
tout : un qui

ecrit, un qui lit. Donc meme en multiprocesseur, il n'aura pas de pb avec
volatil (ou bien

me trompe-je ?).


Ca posera sans doute peu de problèmes sur des architectures où les
lecture/écritures de sa variable sont atomiques (x86 en particulier) et
encore ça présuppose certaines conditions d'alignement
(http://intel.forums.liveworld.com/thread.jsp?forum$2&threada58). De
manière générale tu t'exposes à du "word tearing".

Mais tu as raison de souligné le pb : la seule vrai solution serait un
mutex, mais dans

son cas, cela me parraissait un peu "lourd"...


Patrick Mézard


Avatar
Patrick Mézard
En effet, c'est tout à fait cela : le thread ne modifie pas la variable
globale mais ne teste que sa valeur pour savoir s'il faut sortir ou pas.
Mais j'ai trouvé une autre solution, je fais un TerminateThread() à la
place.


[HS]
TerminateThread est une fonction à fuir de l'API windows. As-tu vraiment lu
la documentation jusqu'au bout ?

[MSDN] TerminateThread
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/base/terminatethread.asp

TerminateThread is a dangerous function that should only be used in the most
extreme cases. You should call TerminateThread only if you know exactly what
the target thread is doing, and you control all of the code that the target
thread could possibly be running at the time of the termination. For
example, TerminateThread can result in the following problems:

If the target thread owns a critical section, the critical section will not
be released.
If the target thread is allocating memory from the heap, the heap lock will
not be released.
If the target thread is executing certain kernel32 calls when it is
terminated, the kernel32 state for the thread's process could be
inconsistent.
If the target thread is manipulating the global state of a shared DLL, the
state of the DLL could be destroyed, affecting other users of the DLL.
[/MSDN]

Je ne connais pas de façon de réaliser ça à moins de faire du polling (pas
super), ou de bricoler un truc avec QueueAPC mais c'est compliqué.

[/HS]

Patrick Mézard

Avatar
M.B.
On le trouve en anglais ici :

http://www.microsoft.com/mspress/books/2345.asp

MB

"M.B." a écrit dans le message news:
bito9j$1kp$
Effectivement une recherche rapide sur le site de
mspress ne donne rien.

Pourtant je l'ai sous les jeux, en francais.

ISBN : 2-84082-386-1

4eme version, 2000

Avec la version electronique sur CD en anglais

Les exemples sont en C, pas en C++

MB


"Jean-François GAZET" a écrit dans le message news:
3f52608e$0$284$
Pour la programmation avancee sous Windows, une autre
'BON' bouquin :

"Developper des applications sous Windows"
Jeffrey Richter
Microsoft Press

(process, thread, semaphore, mutex, etc ...)

MB


Je ne l'ai pas trouvé sur internet. J'ai "Developper des applications
sous


Windows en VB" mais pas de cet auteur et je le VB, bof :-((









Avatar
M.B.
Il suffit d'attendre l'arrivee d'un evenement d'une
maniere non blocante dans la boucle de son thread.

MB

"Patrick Mézard" a écrit dans le message news:
bitnni$v69$
Je ne connais pas de façon de réaliser ça à moins de faire du polling (pas
super), ou de bricoler un truc avec QueueAPC mais c'est compliqué.



Avatar
Jean-François GAZET
On le trouve en anglais ici :
http://www.microsoft.com/mspress/books/2345.asp
MB


Merci

1 2