Download the example here.
HANDLE CreateEvent(
   
LPSECURITY_ATTRIBUTES  lpEventAttributes, //
address of security attributes
    BOOL  bManualReset,                                            
// flag for manual-reset event
    BOOL  bInitialState,                                                
// flag for initial state
    LPCTSTR  lpName                                                 
// address of event-object name 
  
);
lpEventAttribute
--> If you specify NULL value, the event object
is created with default security descriptor.
bManualReset
--> If you want Windows to automatically reset
the event object to nonsignalled state after WaitForSingleObject call,
you must specify FALSE as this parameter. Else you must manually reset
the event object with the call to ResetEvent.
bInitialState
--> If you want the event object to be created
in the signalled state, specify TRUE as this parameter else the event object
will be created in the nonsignalled state.
lpName -->
Pointer to an ASCIIZ string that is the name of the event object. This
name is used when you want to call OpenEvent.
If the call is successful, it returns the handle
to the newly created event object else it returns NULL.
You can modify the state of an event object with
two API calls: SetEvent and ResetEvent. SetEvent function sets the event
object into signalled state. ResetEvent does the reverse.
When the event object is created, you must put
the call to WaitForSingleObject in the thread that wants to watch for the
state of the event object. WaitForSingleObject has the following syntax:
DWORD WaitForSingleObject(
   
HANDLE  hObject,        
// handle of object to wait for
   
DWORD  dwTimeout     
// time-out interval in milliseconds
  
);
hObject -->
A handle to one of the synchronization object. Event object is a type of
synchronization object.
dwTimeout -->
specify the time in milliseconds that this function will wait for the object
to be in signalled state. If the specified time has passed and the event
object is still in nonsignalled state, WaitForSingleObject returns the
the caller. If you want to wait for the object indefinitely, you must specify
the value INFINITE as this parameter.
include windows.inc
includelib user32.lib
includelib kernel32.lib
includelib gdi32.lib
.const
IDM_START_THREAD equ 1
IDM_STOP_THREAD equ 2
IDM_EXIT equ 3
WM_FINISH equ WM_USER+100h
.data
ClassName db "Win32ASMEventClass",0
AppName  db "Win32 ASM Event Example",0
MenuName db "FirstMenu",0
SuccessString db "The calculation is completed!",0
StopString db "The thread is stopped",0
.data?
hInstance HINSTANCE ?
CommandLine LPSTR ?
hwnd HANDLE ?
hMenu HANDLE ?
ThreadID DWORD ?
ExitCode DWORD ?
hEventStart HANDLE ?
EventStop BOOL FALSE
.code
start:
    invoke GetModuleHandle,
NULL
    mov    hInstance,eax
    invoke GetCommandLine
    invoke WinMain, hInstance,NULL,CommandLine,
SW_SHOWDEFAULT
    invoke ExitProcess,eax
WinMain proc hInst:HINSTANCE,hPrevInst:HINSTANCE,CmdLine:LPSTR,CmdShow:SDWORD
    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  hInstance
    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,0
    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
    invoke GetMenu,hwnd
    mov  hMenu,eax
    .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
    mov   eax,uMsg
    .IF eax==WM_CREATE
       
invoke CreateEvent,NULL,FALSE,FALSE,NULL
       
mov  hEventStart,eax
       
mov  eax,OFFSET ThreadProc
       
invoke CreateThread,NULL,NULL,eax,\
                            
NULL,NORMAL_PRIORITY_CLASS,\
                            
ADDR ThreadID
       
invoke CloseHandle,eax
    .ELSEIF eax==WM_DESTROY
       
invoke PostQuitMessage,NULL
    .ELSEIF eax==WM_COMMAND
       
mov eax,wParam
       
.if lParam==0
           
.if ax==IDM_START_THREAD
               
invoke SetEvent,hEventStart
               
invoke EnableMenuItem,hMenu,IDM_START_THREAD,MF_GRAYED
               
invoke EnableMenuItem,hMenu,IDM_STOP_THREAD,MF_ENABLED
           
.elseif ax==IDM_STOP_THREAD
               
mov  EventStop,TRUE
               
invoke EnableMenuItem,hMenu,IDM_START_THREAD,MF_ENABLED
               
invoke EnableMenuItem,hMenu,IDM_STOP_THREAD,MF_GRAYED
           
.else
               
invoke DestroyWindow,hWnd
           
.endif
       
.endif
    .ELSEIF eax==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
       
invoke WaitForSingleObject,hEventStart,INFINITE
       
mov  ecx,600000000
       
.WHILE ecx!=0
               
.if EventStop!=TRUE
                       
add  eax,eax
                       
dec  ecx
               
.else
                       
invoke MessageBox,hwnd,ADDR StopString,ADDR AppName,MB_OK
                       
mov  EventStop,FALSE
                       
jmp ThreadProc
               
.endif
       
.ENDW
       
invoke PostMessage,hwnd,WM_FINISH,NULL,NULL
       
invoke EnableMenuItem,hMenu,IDM_START_THREAD,MF_ENABLED
       
invoke EnableMenuItem,hMenu,IDM_STOP_THREAD,MF_GRAYED
       
jmp   ThreadProc
       
ret
ThreadProc ENDP
end start
    .IF eax==WM_CREATE
       
invoke CreateEvent,NULL,FALSE,FALSE,NULL
       
mov  hEventStart,eax
       
mov  eax,OFFSET ThreadProc
       
invoke CreateThread,NULL,NULL,eax,\
                            
NULL,NORMAL_PRIORITY_CLASS,\
                            
ADDR ThreadID
       
invoke CloseHandle,eax
You can see that I create the event object and the thread during the processing of WM_CREATE message. I create the event object in the nonsignalled state with automatic reset. After the event object is created, I create the thread. However the thread doesn't run immediately because it waits for the event object to be in the signalled state as the code below:
ThreadProc PROC USES ecx Param:DWORD
       
invoke WaitForSingleObject,hEventStart,INFINITE
       
mov  ecx,600000000
The first line of the thread procedure is the
call to WaitForSingleObject. It waits indefinitely for the signalled state
of the event object before it returns. This means that even when the thread
is created, we put it into a dormant state.
When the user selects "run thread" command from
the menu, we set the event object into signalled state as below:
           
.if ax==IDM_START_THREAD
               
invoke SetEvent,hEventStart
The call to SetEvent turns the event object into the signalled state which in turn makes the WaitForSingleObject call in the thread procedure return and the thread starts running. When the user selects "stop thread" command, we set the value of the global variable "EventStop" to TRUE.
               
.if EventStop==FALSE
                       
add  eax,eax
                       
dec  ecx
               
.else
                       
invoke MessageBox,hwnd,ADDR StopString,ADDR AppName,MB_OK
                       
mov  EventStop,FALSE
                       
jmp ThreadProc
               
.endif
This stops the thread and jumps to the WaitForSingleObject
call again. Note that we don't have to manually reset the event object
into nonsignalled state because we specify the bManualReset parameter of
the CreateEvent call as FALSE.