Exemple d'application multithread

Soyez le premier à donner votre avis sur cette source.

Vue 23 424 fois - Téléchargée 1 598 fois

Description

Salut, Comme vous le savez tous, le multithreading n'est pas une chose facile en vb, voir quelque chose d'impossible(comme je l'ai souvent lu). Je precise que ce code ne fonctionnera pas si compilé en vb6.
L'avantage du multithread: éviter le freeze de l'application lorsque vous gerer de lourdes procedures, Ca permet a l'application de garder la main sur les differents events(souris, clavier etc).
Cet exemple simple vous permettras de mieux comprendre: vous avez deux listview. vous y ajouter des items en boucle (5000 dans l'exemple). En tant normal, c'est fini votre application va freezer le temps que ça soit fini (à moins d'utiliser doevents, mais vous savez que l'effet de cet opérateur peut etre catastrophique selon la maniere dont on l'utilise). Avec le threading, ça vous permet d'executer d'autres taches en même temps sans aucun ennui ce type.
Precision: il faut synchroniser les access à l'édition des objets. En théorie (j'ai pas tester) on ne peux pas editer un objet de deux threads distinctes => access violation.
Plus precisement, cette source utilise l'api CreateThread_ByValParam() pour creer les threads, et LocalAlloc() couplé a Copymemory() pour lui passer des parametres de la fonction a executée, appelée elle même par l'opérateur Adressof().

Source / Exemple :


Option Explicit
'Declaration
Private Const MAXLONG = 256

Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (pDest As Any, pSource As Any, ByVal dwLength As Long)
Private Declare Function LocalAlloc Lib "kernel32" (ByVal uFlags As Long, ByVal uBytes As Long) As Long
Private Declare Function LocalFree Lib "kernel32" (ByVal hMem As Long) As Long
Private Declare Function TerminateThread Lib "kernel32" (ByVal hThread As Long, ByVal dwExitCode As Long) As Long
Private Declare Function CreateThread_ByValParam Lib "kernel32" Alias "CreateThread" (ByVal lpThreadAttributes As Long, ByVal dwStackSize As Long, ByVal lpStartAddress As Any, ByVal lpParameter As Long, ByVal dwCreationFlags As Long, ByRef lpThreadId As Long) As Long

Private Const THREAD_BASE_PRIORITY_IDLE = -15
Private Const THREAD_BASE_PRIORITY_LOWRT = 15
Private Const THREAD_BASE_PRIORITY_MAX = 2
Private Const THREAD_BASE_PRIORITY_MIN = -2
Private Const THREAD_PRIORITY_HIGHEST = THREAD_BASE_PRIORITY_MAX
Private Const THREAD_PRIORITY_LOWEST = THREAD_BASE_PRIORITY_MIN
Private Const THREAD_PRIORITY_ABOVE_NORMAL = (THREAD_PRIORITY_HIGHEST - 1)
Private Const THREAD_PRIORITY_BELOW_NORMAL = (THREAD_PRIORITY_LOWEST + 1)
Private Const THREAD_PRIORITY_ERROR_RETURN = (MAXLONG)
Private Const THREAD_PRIORITY_IDLE = THREAD_BASE_PRIORITY_IDLE
Private Const THREAD_PRIORITY_NORMAL = 0
Private Const THREAD_PRIORITY_TIME_CRITICAL = THREAD_BASE_PRIORITY_LOWRT

Private Const CREATE_SUSPENDED = &H4

Public Enum ThreadPriority
    tpLowest = THREAD_PRIORITY_LOWEST
    tpBelowNormal = THREAD_PRIORITY_BELOW_NORMAL
    tpNormal = THREAD_PRIORITY_NORMAL
    tpAboveNormal = THREAD_PRIORITY_ABOVE_NORMAL
    tpHighest = THREAD_PRIORITY_HIGHEST
End Enum

Dim lPtr               As Long

Public Function malloc(sParam As String) As Long
Dim Ptr As Long, lSize As Long
    
lSize = LenB(sParam) 'on recupere la taille de la valeur de la variable a passer en parametre
    
'on alloue un emplacement mémoire, ptr nous retourne la position
Ptr = LocalAlloc(lPtr, lSize + 4)

'si success
If Ptr <> 0 Then

    'on copie la taille (4 bytes = long)
    CopyMemory ByVal Ptr, lSize, 4
    
    'on copie la valeur de la variables. StrPtr pointe a l'adresse du premier chr
    If lSize > 0 Then CopyMemory ByVal Ptr + 4, ByVal StrPtr(sParam), lSize
End If

'on attribue sa valeur a la fonction
malloc = Ptr
End Function

Public Function GetStrFromMemory(lParam As Long) As String
Dim lSize As Long
Dim sBuf  As String

'si le pointeur de la variable est null la valeur retournée de la fonction est null
If lParam = 0 Then
    GetStrFromMemory = ""
Else
    'on récupere la taille
    CopyMemory lSize, ByVal lParam, 4
    
    If lSize > 0 Then
    
        'on prepare un buffer
        sBuf = String(lSize \ 2, 0)
        
        'on récupere le string (lParam)
        CopyMemory ByVal StrPtr(sBuf), ByVal lParam + 4, lSize
        
        'on retourne sa valeur
        GetStrFromMemory = sBuf
    End If
End If
End Function

Public Sub FreeMemory(lParam As Long)
'on libere la memoire
LocalFree lParam
End Sub

Public Function CreateNewThread(ByVal lFunction As Long, Optional ByVal lParam As Long, Optional ByVal lPriority As Long = tpNormal, Optional ByVal lEnabled As Boolean = True)
Dim lFlags     As Long
Dim lpThreadId As Long
Dim lHandle    As Long

'on verifie la valeur du flag pour définir la propriété de la thread a creer
If lEnabled = True Then lFlags = 0 Else lFlags = CREATE_SUSPENDED

'on crée la thread (lHandle retourne son handle lol)
lHandle = CreateThread_ByValParam(ByVal 0&, ByVal 0&, lFunction, ByVal lParam, lFlags, lpThreadId)

'on retourne la valeur du handle
CreateNewThread = lHandle

End Function

Public Function TerminateCurrentThread(lParam As Long)
On Error Resume Next

'on termine la thread
TerminateThread lParam, ByVal 0&

End Function

Conclusion :


tout est dans le zip :)

Codes Sources

A voir également

Ajouter un commentaire Commentaires
cs_eldim Messages postés 956 Date d'inscription lundi 30 mai 2005 Statut Membre Dernière intervention 21 août 2014 1
5 avril 2006 à 14:01
Bonjour,

L'idée semble bonne mais effectivememt ça ne fonctionne pas en vb6...
Alors en quelle version de vb cela fonctionne-t-il ? (car cela ne ressemble pas à du vb.net...)
FeelCode Messages postés 278 Date d'inscription vendredi 16 avril 2004 Statut Membre Dernière intervention 27 avril 2006 1
5 avril 2006 à 14:06
bof existe deja et dasn pas mal d'exemple don mon source....
bref sans grand interer ,a part que je dirait que : le multi tread c est vraiment a eviter dans la mesure du possible. si dans certaine situation on ne peut faire autrement par ex une boucle infinie velontaire pour faire un control sur quelque chose.
sinon doevents est peut etre un peut lent mai a ce moment la on peut faire un teste par exemple faire 1 doevents sur 100 passage de boucle
de plus un tread c est pas vraiment bien decharger un foit terminer
thel0rd Messages postés 14 Date d'inscription lundi 16 février 2004 Statut Membre Dernière intervention 20 janvier 2012
5 avril 2006 à 14:10
VB5 uniquement, en vb6 ça crash sans arret, au maximum tu peux threader une sub, mais des qu'il passer un argument c'est foutu...
J'ajoute par la même occasion qu'il est possible de débugguer la source avec l'IDE de vb5, mais pas step by step. alors vous me direz quelle utilité? ben en mode debug vous aurez au moins le message d'erreur de vb avant que l'IDE plante donc on peut quand même fixer. en compilé, une erreur dans la thread et c'est un plantage sans aucune forme de remerciement. Il vaut mieux etre sur a 100% de sa foncton avant de la threader.
FeelCode Messages postés 278 Date d'inscription vendredi 16 avril 2004 Statut Membre Dernière intervention 27 avril 2006 1
5 avril 2006 à 14:14
il faut compiler en Pcode et non en natif ou l'inverse je me souvient plus, et enfin pour passer les argument je dirai qu'il vaut mieut passer par un variable public pour contourner le probleme.
thel0rd Messages postés 14 Date d'inscription lundi 16 février 2004 Statut Membre Dernière intervention 20 janvier 2012
5 avril 2006 à 14:21
Evidemment, FeelCode tu as raison aussi quand tu dis qu'il ne faut utiliser le threading que lorsqu'on en a besoin, mais un bon handling des erreurs et ça reste assez stable. Je l'utilise pour tout ce que je fais necessitant un traitement "lourd" d'information. D'ailleurs si tu peux me donner le lien de ton code que je jette un oeil, je n'ai jamais une seule source en vb qui permette de threader sans accroc en passant une valeur a lParameter, et en vb6 je crois même pas que ce soit possible sans plantage.

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.