分享
 
 
 

事件对象

王朝c/c++·作者佚名  2006-01-06
窄屏简体版  字體: |||超大  

本课中我们将要学习事件对象以及如何在多线程编程中如何使用同步对象。

理论:

上一课中我们演示了如何用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 \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_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。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有