Bon depuis que je code en purebasic, je suis toujours embêté avec ces fichus threads. A chaque fois qu'on veut passer plusieurs paramètres à un thread, il faut bidouiller une structure et faire hyper attention à ce qu'on fait.
En général, lorsqu'on veut passer plusieurs paramètres à un thread, on conçoit une structure (rien que pour ça bien souvent), et on met dans cette structure tout ce qu'on veut envoyer à notre thread. Alors c'est plutôt une bonne technique sauf que:
1° On est obligé de concevoir une structure rien que pour cela
2° Si on veut rajouter un paramètre, il faut changer la structure
3° On se retrouve souvent avec des "Invalid Memory Access"
Je vais insister sur ce dernier point: l'une des raisons qui fait qu'on a des erreurs d'accès mémoire c'est qu'on passe la structure à notre thread par pointeur. De ce fait, il faut que ce pointeur et toutes les données qu'il contient restent valides durant toute la vie du thread. Et parfois, on oublie ou on copie mal certaines données qui font que ben .. ca plante sans qu'on comprenne pourquoi.
Je donne un exemple:
Code : Tout sélectionner
Structure test
param1.i
param2.s
EndStructure
;structure du thread
Structure th
var1.i
var2.s
var.test
EndStructure
Procedure thread(*paramList.th)
Delay(2000) ;attente de la fin de la fonction appelante
Debug *paramList\var1
Debug *paramList\var2
Debug *paramList\var\param1
Debug *paramList\var\param2
EndProcedure
Procedure callThread()
var1.i = 1234
var2.s = "test"
var.test\param1 = 789
var\param2 = "Hello World !"
envoi.th
envoi\var1 = var1
envoi\var2 = var2
envoi\var = var
t = CreateThread(@thread(), @envoi)
ProcedureReturn t
EndProcedure
WaitThread(callThread())
Pour palier à ce problème j'ai donc fait quelques fonctions qui permettent de nous simplifier la vie. Ces procédures permettent d'ajouter simplement des paramètres à une unique ressource. C'est ensuite cette ressources qui est passée au thread et d'autres procédures permettent de récupérer les différents paramètres de la ressource:
Code : Tout sélectionner
; **************************************************
; Gestionnaire de passage de parametres à un Thread.
; Par SERIN Kévin
; PB 4.51
; **************************************************
;Structure contenant la liste des adresses des parametres.
Structure PThread
List param.i()
EndStructure
;Instancie une liste de paramètres.
; return: une ressource de type PThread.
Procedure pThread_create()
*pThread.PThread = AllocateMemory(SizeOf(PThread))
NewList *pThread\param()
ProcedureReturn *pThread
EndProcedure
;Fait une copie de la donnée et l'ajoute à la liste des paramètres.
;Attention: pour les structures, utilisez la macro pThread_addStruct().
; pThread: ressource PThread (créée avec pThread_create() )
; value: adresse de la donnée à ajouter
; size: taille de la donnée à ajouter
Procedure pThread_addValue(*pThread.PThread, *value, size.i)
*newElement = AllocateMemory(size)
CopyMemory(*value, *newElement, size)
AddElement(*pThread\param())
*pThread\param() = *newElement
EndProcedure
;Ajoute directement une adresse à la liste des paramètres.
;Attention: aucune copie n'est effectuée, la zone mémoire doit donc restée accessible à tout moment. Préférez pThread_addValue().
; pThread: ressource PThread (créée avec pThread_create() ).
; adrs: adresse à ajouter.
Procedure pThread_addAddress(*pThread.PThread, *adrs)
AddElement(*pThread\param())
*pThread\param() = *adrs
EndProcedure
;Récupère l'adresse du ième paramètre (commence à 1).
; pThread: ressource PThread (créée avec pThread_create() ).
; i: index du paramètre.
Procedure pThread_get(*pThread.PThread, i.i)
SelectElement(*pThread\param(), i-1)
ProcedureReturn *pThread\param()
EndProcedure
;Libère une ressource PThread ainsi que tous les paramètres
; pThread: ressource PThread (créée avec pThread_create() ).
Procedure pThread_free(*pThread.PThread)
ForEach *pThread\param()
FreeMemory(*pThread\param())
Next
ClearList(*pThread\param())
FreeMemory(*pThread)
EndProcedure
;Macro permettant d'ajouter une structure à la liste des paramètres.
; pThread: ressource PThread (créée avec pThread_create() ).
; varAdrs: adresse de la variable contenant la structure à ajouter.
; tempVar: nom de variable temporaire (poubelle). Ce nom ne doit pas être utilisé par une autre variable de votre code.
; struct: nom de la structure de la variable.
Macro pThread_addStruct(pThread, varAdrs, tempVar, struct)
tempVar = AllocateMemory(SizeOf(struct))
CopyStructure(varAdrs, tempVar, struct)
pThread_addAddress(pThread, tempVar)
EndMacro
Code : Tout sélectionner
; ********
; Exemple:
; ********
Structure test
param1.i
param2.s
EndStructure
Procedure thread(paramList)
Delay(2000) ;attente de la fin de la fonction appelante
var1.i = PeekI(pThread_get(paramList, 1)) ;récupération du 1er parametre
var2.s = PeekS(pThread_get(paramList, 2)) ;récupération du 2e parametre
*varStruct.test = pThread_get(paramList, 3) ;récupération du 3e parametre
Debug var1
Debug var2
Debug *varStruct\param1
Debug *varStruct\param2
pThread_free(paramList) ;liberation des ressources à la fin du thread
EndProcedure
Procedure callThread()
var1.i = 1234
var2.s = "test"
var.test\param1 = 789
var\param2 = "Hello World !"
param = pThread_create()
pThread_addValue(param, @var1, SizeOf(Integer))
pThread_addValue(param, @var2, Len(var2)+1)
pThread_addStruct(param, @var, tmp, test)
t = CreateThread(@thread(), param)
ProcedureReturn t
EndProcedure
WaitThread(callThread())
Voilà en espérant que cela vous serve à quelque chose.