Downloadez l'exemple ici.
CreateThread
proto lpThreadAttributes:DWORD,\
dwStackSize:DWORD,\
lpStartAddress:DWORD,\
lpParameter:DWORD,\
dwCreationFlags:DWORD,\
lpThreadId:DWORD
Le fonctionnent de CreateThread ressemble beaucoup à celui de CreateProcess.
lpThreadAttributes
Vous pouvez le mettre à 0 (NULL) si vous souhaitez que le lien soit le descripteur de sécurité par défaut.
dwStackSize
Ça spécifie la taille à réserver sur la pile pour le lien. Si vous voulez que le lien ait la même taille de pile que le lien primaire, employez le 0 (NULL) pour ce paramètre.
lpStartAddress Adresse de la fonction qui fait le 'lien'. C'est la fonction qui exécutera le travail (qui fera le lien). Cette fonction DOIT recevoir un et seulement un paramètre 32 bits et renvoyer une valeur sur 32 bits.
lpParameter C'est le paramètre que vous devez passer à la fonction 'lien'.
dwCreationFlags 0 signifie que le lien prend le commandement immédiatement après qu'il est été créé. L'opposé c'est le flag 'CREATE_SUSPENDED'.
lpThreadId La fonction 'CreateThread' donnera l'ID du nouveau lien créé à cette adresse.
Si l'appel de CreateThread s'est déroulé avec succès, il rend l'handle du lien nouvellement créé. Sinon, il renvoie le NULL.
La fonction de lien en en cours aussitôt après que l'appel de CreateThread soit un succès, à moins que vous ne mettez le flag 'CREATE_SUSPENDED' dans dwCreationFlags. Dans ce cas, le lien est suspendu jusqu'à ce que la fonction ResumeThread soit appelée.
Après les retours de la 'fonction de lien' (avec l'instruction ret), Windows appelle la fonction ExitThread tout seul. Mais vous pouvez appeler la fonction ExitThread dans votre 'fonction de lien' par vous-même, mais là je développerai pas !
Vous pouvez retrouver le code de sortie d'un lien en appelant la fonction GetExitCodeThread.
Si vous voulez terminer un lien, vous pouvez appeler la fonction TerminateThread. Mais vous devez employer cette fonction seulement dans des circonstances extrêmes puisque cette fonction termine le lien immédiatement sans lui donner aucune chance de se fermer proprement, sans laissez derrière lui des valeurs qui lui sont spécifiques dans certaines variables.
Maintenant on va vous montrer les méthodes de communications entre les liens.
Il y en a trois:
WM_MYCUSTOMMSG equ WM_USER+100h
Windows n'emploiera jamais aucune valeur WM_USER vers ses propres messages donc vous pouvez employer la valeur WM_USER pour votre propres messages faits sur mesure.
Si un des lien est un lien d'interface utilisateur (le lien primaire, le Gouverneur) et un autre est un des 'personnel du gouverneur', vous ne pouvez pas employer cette méthode en tant que communication bilatérale puisque un lien 'personnel' ne possède pas sa propre fenêtre. Donc il n'a y pas de file d'attente de message.
Vous pouvez employer le schéma suivant :
User interface Thread ------> global variable(s)----> Worker thread
Worker Thread ------> custom window message(s) ----> User interface
Thread
Soit en Français:
Lien d'interface d'utilisateur (primaire)------> variable(s) globale(s)----> lien de travail (personnel)
lien de travail (personnel)------>'message(s) de fenêtre' conçu sur mesure----> lien d'interface d'utilisateur
En fait, nous employons cette méthode dans notre exemple.
La dernière sorte de communication c'est l'événement objet. Vous pouvez vous représenter l'événement' comme une sorte de flag. Si l'événement est dans l'état "non signalé", le lien est inerte ou en sommeil, dans cet état, le lien ne reçoit pas d'ordre du CPU. Quand l'événement est dans l'état "signalé", Windows "réveille" le lien et il commence à exécuter la tâche assignée.
.386
.model
flat,stdcall
option
casemap:none
WinMain
proto :DWORD,:DWORD,:DWORD,:DWORD
include
\masm32\include\windows.inc
include
\masm32\include\user32.inc
include
\masm32\include\kernel32.inc
includelib
\masm32\lib\user32.lib
includelib
\masm32\lib\kernel32.lib
.const
IDM_CREATE_THREAD
equ 1
IDM_EXIT
equ 2
WM_FINISH
equ WM_USER+100h
.data
ClassName
db "Win32ASMThreadClass",0
AppName
db "Win32 ASM MultiThreading Example",0
MenuName
db "FirstMenu",0
SuccessString
db "The calculation is completed!",0
.data?
hInstance
HINSTANCE ?
CommandLine
LPSTR ?
hwnd
HANDLE ?
ThreadID
DWORD ?
.code
start:
invoke GetModuleHandle, NULL
mov hInstance,eax
invoke GetCommandLine
mov CommandLine,eax
invoke WinMain, hInstance,NULL,CommandLine, SW_SHOWDEFAULT
invoke ExitProcess,eax
WinMain
proc hInst:HINSTANCE,hPrevInst:HINSTANCE,CmdLine:LPSTR,CmdShow:DWORD
LOCAL wc:WNDCLASSEX
LOCAL msg:MSG
mov wc.cbSize,SIZEOF WNDCLASSEX
mov wc.style, CS_HREDRAW or CS_VREDRAW
mov wc.lpfnWndProc, OFFSET WndProc
mov wc.cbClsExtra,NULL
mov wc.cbWndExtra,NULL
push hInst
pop wc.hInstance
mov wc.hbrBackground,COLOR_WINDOW+1
mov wc.lpszMenuName,OFFSET MenuName
mov wc.lpszClassName,OFFSET ClassName
invoke LoadIcon,NULL,IDI_APPLICATION
mov wc.hIcon,eax
mov wc.hIconSm,eax
invoke LoadCursor,NULL,IDC_ARROW
mov wc.hCursor,eax
invoke RegisterClassEx, addr wc
invoke CreateWindowEx,WS_EX_CLIENTEDGE,ADDR ClassName,ADDR AppName,\
WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,\
CW_USEDEFAULT,300,200,NULL,NULL,\
hInst,NULL
mov hwnd,eax
invoke ShowWindow, hwnd,SW_SHOWNORMAL
invoke UpdateWindow, hwnd
.WHILE TRUE
invoke GetMessage, ADDR msg,NULL,0,0
.BREAK .IF (!eax)
invoke TranslateMessage, ADDR msg
invoke DispatchMessage, ADDR msg
.ENDW
mov eax,msg.wParam
ret
WinMain
endp
WndProc
proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
.IF uMsg==WM_DESTROY
invoke PostQuitMessage,NULL
.ELSEIF uMsg==WM_COMMAND
mov eax,wParam
.if lParam==0
.if ax==IDM_CREATE_THREAD
mov eax,OFFSET ThreadProc
invoke CreateThread,NULL,NULL,eax,\
0,\
ADDR ThreadID
invoke CloseHandle,eax
.else
invoke DestroyWindow,hWnd
.endif
.endif
.ELSEIF uMsg==WM_FINISH
invoke MessageBox,NULL,ADDR SuccessString,ADDR AppName,MB_OK
.ELSE
invoke DefWindowProc,hWnd,uMsg,wParam,lParam
ret
.ENDIF
xor eax,eax
ret
WndProc
endp
ThreadProc
PROC USES ecx Param:DWORD
mov ecx,600000000
Loop1:
add eax,eax
dec ecx
jz Get_out
jmp Loop1
Get_out:
invoke PostMessage,hwnd,WM_FINISH,NULL,NULL
ret
ThreadProc ENDP
end start
.if ax==IDM_CREATE_THREAD
mov eax,OFFSET ThreadProc
invoke CreateThread,NULL,NULL,eax,\
NULL,0,\
ADDR ThreadID
invoke CloseHandle,eax
La susdite fonction crée un lien qui contrôlera une procédure nommée ThreadProc en parallèle avec le lien primaire. Après que cet appel soit couronné de succès, CreateThread revoie ses valeurs de retours immédiatement et ThreadProc se lance. Puisque nous n'employons pas d'handle de lien, nous devons le fermer sinon il y aura des fuites de mémoire. Notez que la fermeture de l'handle du lien ne termine pas ce lien. Son seul effet est que désormais nous ne pourrons plus employer l'handle du lien.
ThreadProc
PROC USES ecx Param:DWORD
mov ecx,600000000
Loop1:
add eax,eax
dec ecx
jz Get_out
jmp Loop1
Get_out:
invoke PostMessage,hwnd,WM_FINISH,NULL,NULL
ret
ThreadProc ENDP
Comme vous pouvez le voir, ThreadProc exécute un calcul sauvage (un calcul immense qui occupe le système) qui prend un longue période de temps avant de se terminer, et quand il est finit il envoie enfin le message WM_FINISH vers la fenêtre principale. WM_FINISH est notre message (celui qu'on a créé sur mesure). Il est ainsi défini :