📄 lion-tut-c16.htm
字号:
<HTML>
<head>
<link rel="stylesheet" href="../../asm.css">
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<title>Iczelion's win32 asm tutorial</title>
</head>
<body bgcolor="#FFFFFF" background="../../images/back01.jpg">
<P align=center><FONT color=#0000ff size=+2>第十六课 事件对象</FONT></P>
<HR SIZE=1>
<STRONG></STRONG>本课中我们将要学习事件对象以及如何在多线程编程中如何使用同步对象。
<H3><FONT
color=#ff0000>理论:</FONT></H3>上一课中我们演示了如何用WINDOWS消息在不同的线程之间进行通讯。另外的两种,即:使用全局变量和事件对象,将在本课中讲解。
<BR>事件对象就像一个开关:它只有两种状态---开和关。当一个事件处于”开”状态,我们称其为”有信号”否则称为”无信号”。您可以在一个线程的执行函数中创建一个事件对象,然后观察它的状态,如果是”无信号”就让该线程睡眠,这样该线程占用的CPU时间就比较少。
<BR>产生事件对象的函数如下:
<P><B>CreateEvent proto lpEventAttributes:DWORD,\</B>
<BR><B>
bManualReset:DWORD,\</B>
<BR><B>
bInitialState:DWORD,\</B>
<BR><B>
lpName:DWORD</B>
<P><B>lpEventAttribute</B>-->
如果是NULL值,产生的事件对象有缺省的安全属性。<BR><B>bManualReset</B>-->
如果想在每次调用WaitForSingleObject
后让WINDOWS为您自动地把事件地状态恢复为”无信号”状态,必须把该参数设为FALSE,否则,您必须每次调用ResetEvent函数来清除事件的信号。<BR><B>bInitialState</B>-->
刚刚产生事件对象时的状态。如果设为TRUE是”有信号”,否则是”无信号”。<BR><B>lpName</B> -->
事件对象的名称。您在OpenEvent函数中可能使用。
<P>如果CreateEvent调用成功的话,会返回新生成的对象的句柄,否则返回NULL。<BR>这里有两个API函数用来修改事件对象的信号状态:SetEvent和ResetEvent。前者把事件对象设为”有信号”状态,而后者正好相反。<BR>在事件对象生成后,必须调用WaitForSingleObject来让线程进入等待状态,该函数的语法如下:
<P><B>WaitForSingleObject proto hObject:DWORD, dwTimeout:DWORD</B>
<P><B>hObject</B> -->指向同步对象的指针。事件对象其实是同步对象的一种。<BR><B>dwTimeout </B>-->
等待同步对象变成”有信号”前等待的时间,以毫秒计。当等待的时间超过该值后无信号同步对象仍处于”无信号”状态,线程不再等待,WaitForSingleObject函数会返回。如果想要线程一直等待,请把该参数设为INFINITE(该值等于0xffffffff)。
<H3><FONT color=#ff0000>例子:</FONT></H3>下面的例子显示了一个窗口,当用户选择了菜单项”run
thread”后,线程开始简单的计数运算。结束后弹出一个对话框通知用户。在整个的计数期间,您可以选择菜单项”stop thread”来随时终止线程。
<P><B>.386</B> <BR><B>.model flat,stdcall</B> <BR><B>option casemap:none</B>
<BR><B>WinMain proto :DWORD,:DWORD,:DWORD,:DWORD</B> <BR><B>include
\masm32\include\windows.inc</B> <BR><B>include \masm32\include\user32.inc</B>
<BR><B>include \masm32\include\kernel32.inc</B> <BR><B>includelib
\masm32\lib\user32.lib</B> <BR><B>includelib \masm32\lib\kernel32.lib</B>
<P><B>.const</B> <BR><B>IDM_START_THREAD equ 1</B> <BR><B>IDM_STOP_THREAD equ
2</B> <BR><B>IDM_EXIT equ 3</B> <BR><B>WM_FINISH equ WM_USER+100h</B>
<P><B>.data</B> <BR><B>ClassName db "Win32ASMEventClass",0</B>
<BR><B>AppName db "Win32 ASM Event Example",0</B> <BR><B>MenuName db
"FirstMenu",0</B> <BR><B>SuccessString db "The calculation is completed!",0</B>
<BR><B>StopString db "The thread is stopped",0</B> <BR><B>EventStop BOOL
FALSE</B>
<P><B>.data?</B> <BR><B>hInstance HINSTANCE ?</B> <BR><B>CommandLine LPSTR ?</B>
<BR><B>hwnd HANDLE ?</B> <BR><B>hMenu HANDLE ?</B> <BR><B>ThreadID DWORD ?</B>
<BR><B>ExitCode DWORD ?</B> <BR><B>hEventStart HANDLE ?</B>
<P><B>.code</B> <BR><B>start:</B> <BR><B> invoke
GetModuleHandle, NULL</B> <BR><B> mov
hInstance,eax</B> <BR><B> invoke GetCommandLine</B>
<BR><B> mov CommandLine,eax</B> <BR><B>
invoke WinMain, hInstance,NULL,CommandLine, SW_SHOWDEFAULT</B>
<BR><B> invoke ExitProcess,eax</B>
<P><B>WinMain proc
hInst:HINSTANCE,hPrevInst:HINSTANCE,CmdLine:LPSTR,CmdShow:DWORD</B>
<BR><B> LOCAL wc:WNDCLASSEX</B> <BR><B>
LOCAL msg:MSG</B> <BR><B> mov wc.cbSize,SIZEOF
WNDCLASSEX</B> <BR><B> mov wc.style, CS_HREDRAW or
CS_VREDRAW</B> <BR><B> mov wc.lpfnWndProc, OFFSET
WndProc</B> <BR><B> mov wc.cbClsExtra,NULL</B>
<BR><B> mov wc.cbWndExtra,NULL</B>
<BR><B> push hInst</B> <BR><B>
pop wc.hInstance</B> <BR><B> mov
wc.hbrBackground,COLOR_WINDOW+1</B> <BR><B> mov
wc.lpszMenuName,OFFSET MenuName</B> <BR><B> mov
wc.lpszClassName,OFFSET ClassName</B> <BR><B> invoke
LoadIcon,NULL,IDI_APPLICATION</B> <BR><B> mov
wc.hIcon,eax</B> <BR><B> mov wc.hIconSm,eax</B>
<BR><B> invoke LoadCursor,NULL,IDC_ARROW</B>
<BR><B> mov wc.hCursor,eax</B>
<BR><B> invoke RegisterClassEx, addr wc</B>
<BR><B> invoke CreateWindowEx,WS_EX_CLIENTEDGE,ADDR
ClassName,\</B>
<BR><B>
ADDR AppName,\</B>
<BR><B>
WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,\</B>
<BR><B>
CW_USEDEFAULT,300,200,NULL,NULL,\</B>
<BR><B>
hInst,NULL</B> <BR><B> mov hwnd,eax</B>
<BR><B> invoke ShowWindow, hwnd,SW_SHOWNORMAL</B>
<BR><B> invoke UpdateWindow, hwnd</B>
<BR><B> invoke GetMenu,hwnd</B> <BR><B>
mov hMenu,eax</B> <BR><B> .WHILE TRUE</B>
<BR><B> invoke
GetMessage, ADDR msg,NULL,0,0</B>
<BR><B> .BREAK
.IF (!eax)</B>
<BR><B> invoke
TranslateMessage, ADDR msg</B>
<BR><B> invoke
DispatchMessage, ADDR msg</B> <BR><B> .ENDW</B>
<BR><B> mov eax,msg.wParam</B>
<BR><B> ret</B> <BR><B>WinMain endp</B>
<P><B>WndProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM</B>
<BR><B> .IF uMsg==WM_CREATE</B>
<BR><B> invoke
CreateEvent,NULL,FALSE,FALSE,NULL</B>
<BR><B> mov hEventStart,eax</B>
<BR><B> mov eax,OFFSET
ThreadProc</B> <BR><B> invoke
CreateThread,NULL,NULL,eax,\</B>
<BR><B>
NULL,0,\</B>
<BR><B>
ADDR ThreadID</B> <BR><B> invoke
CloseHandle,eax</B> <BR><B> .ELSEIF uMsg==WM_DESTROY</B>
<BR><B> invoke
PostQuitMessage,NULL</B> <BR><B> .ELSEIF uMsg==WM_COMMAND</B>
<BR><B> mov eax,wParam</B>
<BR><B> .if lParam==0</B>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -