ITPub博客

首页 > IT职业 > IT生活 > iczelion tut16 (转)

iczelion tut16 (转)

原创 IT生活 作者:gugu99 时间:2007-10-31 16:31:50 0 删除 编辑
iczelion tut16 (转)[@more@]

Tutorial 16: Event object


We will learn what an event object is and how to use it in a multithreaded program.

DOWNLOAD the example here.

Theory:

From the previous tutorial, I demonstrated how threads communicate with a custom window message. I left out two other methods: global variable and event object. We will use both of them in this tutorial.
An event object is like a switch: it has only two states: on or off. When an event object is turned on, it's in the "signalled" state. When it is turned off, it's in the "nonsignalled" state. You create an event object and put in a code snippet in the relevant threads to watch for the state of the event object. If the event object is in the nonsignalled state, the threads that wait for it will be asleep.When the threads are in wait state, they consume little cpu time.
You create an event object by calling CreateEvent function which has the following syntax:

CreateEvent proto lpEventAttributes:Dword,
  bManualReset:DWORD,
  bInitialState:DWORD,
  lpName:DWORD

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:

WaitForSingleObject proto hObject:DWORD, dwTimeout:DWORD

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.

Example:

The example below displays a window waiting for the user to select a command from the menu. If the user selects "run thread", the thread starts the savage calculation. When it's finished, a message box appears infoRming the user that the job is done. During the time that the thread is running, the user can select "stop thread" to stop the thread.

.386
.model flat,stdcall
option casemap:none
WinMain proto :DWORD,:DWORD,:DWORD,:DWORD
include masm32includewindows.inc
include masm32includeuser32.inc
include masm32includekernel32.inc
includelib masm32libuser32.lib
includelib masm32libkernel32.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
EventStop BOOL FALSE

.data?
hInstance HINSTANCE ?
CommandLine LPSTR ?
hwnd HANDLE ?
hMenu HANDLE ?
ThreadID DWORD ?
ExitCode DWORD ?
hEventStart HANDLE ?

.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
  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
  .IF uMsg==WM_CREATE
  invoke CreateEvent,NULL,FALSE,FALSE,NULL
  mov  hEventStart,eax
  mov  eax,OFFSET ThreadProc
  invoke CreateThread,NULL,NULL,eax,
  NULL,0,
  ADDR ThreadID
  invoke CloseHandle,eax
  .ELSEIF uMsg==WM_DESTROY
  invoke PostQuitMessage,NULL
  .ELSEIF uMsg==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 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
  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

Analysis:

In this example, I demonstrate another thread technique.

  .IF uMsg==WM_CREATE
  invoke CreateEvent,NULL,FALSE,FALSE,NULL
  mov  hEventStart,eax
  mov  eax,OFFSET ThreadProc
  invoke CreateThread,NULL,NULL,eax,
  NULL,0,
  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 infinitely 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.


来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/10748419/viewspace-980172/,如需转载,请注明出处,否则将追究法律责任。

上一篇: iczelion tut14 (转)
下一篇: iczelion tut18 (转)
请登录后发表评论 登录
全部评论
  • 博文量
    3122
  • 访问量
    2226347