事件物件(轉)
本課中我們將要學習事件物件以及如何在多執行緒程式設計中如何使用同步物件。
理論:
上一課中我們演示瞭如何用WINDOWS訊息在不同的執行緒之間進行通訊。另外的兩種,即:使用全域性變數和事件物件,將在本課中講解。
事件物件就像一個開關:它只有兩種狀態---開和關。當一個事件處於”開”狀態,我們稱其為”有訊號”否則稱為”無訊號”。您可以在一個執行緒的執行函式中建立一個事件物件,然後觀察它的狀態,如果是”無訊號”就讓該執行緒睡眠,這樣該執行緒佔用的CPU時間就比較少。
產生事件物件的函式如下:
CreateEvent proto lpEventAttributes:DWORD,
bManualReset:DWORD,
bInitialState:DWORD,
lpName:DWORD
lpEventAttribute--> 如果是NULL值,產生的事件物件有預設的屬性。
bManualReset--> 如果想在每次呼叫WaitForSingleObject 後讓WINDOWS為您自動地把事件地狀態恢復為”無訊號”狀態,必須把該引數設為FALSE,否則,您必須每次呼叫ResetEvent函式來清除事件的訊號。
bInitialState--> 剛剛產生事件物件時的狀態。如果設為TRUE是”有訊號”,否則是”無訊號”。
lpName --> 事件物件的名稱。您在OpenEvent函式中可能使用。
如果CreateEvent呼叫成功的話,會返回新生成的物件的控制程式碼,否則返回NULL。
這裡有兩個API函式用來修改事件物件的訊號狀態:SetEvent和ResetEvent。前者把事件物件設為”有訊號”狀態,而後者正好相反。
在事件物件生成後,必須呼叫WaitForSingleObject來讓執行緒進入等待狀態,該函式的語法如下:
WaitForSingleObject proto hObject:DWORD, dwTimeout:DWORD
hObject -->指向同步物件的指標。事件物件其實是同步物件的一種。
dwTimeout --> 等待同步物件變成”有訊號”前等待的時間,以毫秒計。當等待的時間超過該值後無訊號同步物件仍處於”無訊號”狀態,執行緒不再等待,WaitForSingleObject函式會返回。如果想要執行緒一直等待,請把該引數設為INFINITE(該值等於0xffffffff)。
例子:
下面的例子顯示了一個視窗,當使用者選擇了選單項”run thread”後,執行緒開始簡單的計數運算。結束後彈出一個對話方塊通知使用者。在整個的計數期間,您可以選擇選單項”stop 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
分析:
本例中,我們演示另一種技巧:
.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
在WM_CREATE 訊息的處理中我們生成事件同步物件並建立執行緒。我們設定了相關的值讓同步物件生成時處於”無訊號”狀態而且在呼叫了WaitForSingleObject後可以自動把事件物件的狀態設為”無訊號”。然後我們建立執行緒。 執行緒的程式碼開始執行後立即被阻塞:
ThreadProc PROC USES ecx Param:DWORD
invoke WaitForSingleObject,hEventStart,INFINITE
mov ecx,600000000
您可以看到執行緒的執行體的第一條程式碼就是呼叫WaitForSingleObject函式,該函式使得執行緒阻塞並且一直處於等待事件物件變成”有訊號”。這也就是說,我們以開始就讓該執行緒進入了睡眠狀態。 當使用者選擇了選單項”run thread”後,我們把事件物件得狀態變成”有訊號”:
.if ax==IDM_START_THREAD
invoke SetEvent,hEventStart
函式SetEvent可以讓同步物件變成”有訊號”狀態,那麼下一次執行緒得到時間片執行時,WaitForSingleObject函式就會返回,執行緒餘下的程式碼就可以得到執行了。當使用者選擇了選單項”stop thread” 時,我們把全域性變數EventStop設為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
這樣執行緒得計數工作結束,然後跳轉到重新執行WaitForSingleObject函式的地方。注意:我們不用手動清除事件物件的訊號,因為在呼叫CreateEvent函式時把引數bManualReset的值設為了FALSE。
[@more@]來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10172717/viewspace-928730/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 理解物件以及物件的屬性、方法、事件 (轉)物件事件
- javaScript事件(三)事件物件JavaScript事件物件
- Vue事件獲取觸發事件物件和繫結事件物件Vue事件物件
- jQuery事件物件jQuery事件物件
- JavaScript 事件物件JavaScript事件物件
- JS的事件物件與事件機制JS事件物件
- javaScript事件,Bom,Dom物件JavaScript事件物件
- js中事件物件eventJS事件物件
- js 註冊事件物件JS事件物件
- Javascript中的事件物件和事件型別JavaScript事件物件型別
- JavaScript瀏覽器事件物件JavaScript瀏覽器事件物件
- JavaScript學習12:事件物件JavaScript事件物件
- 自定義事件相容處理物件事件物件
- javascript基礎(事件物件)(三十一)JavaScript事件物件
- jquery 事件物件屬性小結jQuery事件物件
- JS json字串轉物件、物件轉字串JSON字串物件
- javascript如何獲取事件目標物件JavaScript事件物件
- 關於事件物件中的stopImmediatePropagation事件物件
- iOS事件攔截和事件轉發iOS事件
- 物件轉型物件
- FileSystemObject 物件 (轉)Object物件
- 返回物件(轉)物件
- Shell 物件(轉)物件
- jquery物件如何轉化成DOM物件jQuery物件
- [轉] jQuery物件與DOM物件之間的轉換jQuery物件
- JavaScript 複習之 事件模型 和 Event物件JavaScript事件模型物件
- jQuery事件物件event的屬性和方法jQuery事件物件
- javascript如何獲取觸發事件的物件JavaScript事件物件
- javascript event事件物件相容性問題JavaScript事件物件
- 物件儲存服務的事件通知特性物件事件
- Event Handler 事件處理程式 2 —跨瀏覽器事件物件《高程3》事件瀏覽器物件
- jQuery物件與DOM物件之轉換jQuery物件
- Latch free等待事件(轉)事件
- 10046事件(轉)事件
- Oracle 跟蹤事件【轉】Oracle事件
- 事件營銷(轉載)事件
- java 宣告物件(轉)Java物件
- 和我一起理解js中的事件物件JS事件物件