WIN32汇编语言教程:第12章 多线程 · 12.3 使用事件对象控制线程(2)
12.3.3 进一步改进计数程序
现在让我们进一步改进前面的计数程序,用事件对象代替暂停标志,用WaitForSingleObject函数代替测试暂停标志的语句,这样就可以解决CPU占用率的问题。改进的步骤如下:
● 在程序初始化的时候用CreateEvent函数建立事件对象,以便当做暂停标志使用。
● 当计数线程开始的时候,使用SetEvent函数将事件的初始状态设置为“置位”。
● 计数循环中使用WaitForSingleObject函数测试事件状态,当不需要暂停的时候,由于事件的状态为“置位”,函数会马上返回,循环继续执行。主线程中通过使用ResetEvent函数将事件复位来暂停线程,因为这时进入WaitForSingleObject函数后不会返回,直到主线程中继续使用SetEvent函数将事件置位为止。
● 退出程序的时候用CloseHandle函数删除事件对象。
修改后的代码在所附光盘的Chapter12\Event目录中,Counter.rc文件并没有改动。改动后的Counter.asm文件如下:
.386 .model flat, stdcall option casemap :none ;#################################################################### ; Include 文件定义 ;#################################################################### include windows.inc include user32.inc includelib user32.lib include kernel32.inc includelib kernel32.lib ;#################################################################### ; Equ 等值定义 ;#################################################################### ICO_MAIN equ 1000 DLG_MAIN equ 1000 IDC_COUNTER equ 1001 IDC_PAUSE equ 1002 ;#################################################################### ; 数据段 ;#################################################################### .data? hInstance dd ? hWinMain dd ? hWinCount dd ? hWinPause dd ? hEvent dd ? ;事件对象句柄 dwOption dd ? F_PAUSE equ 0001h F_STOP equ 0002h F_COUNTING equ 0004h .const szStop db '停止计数',0 szStart db '计数',0 ;#################################################################### ; 代码段 ;#################################################################### .code ;#################################################################### _Counter proc uses ebx esi edi,_lParam or dwOption,F_COUNTING and dwOption,not (F_STOP or F_PAUSE) invoke SetEvent,hEvent invoke SetWindowText,hWinCount,addr szStop invoke EnableWindow,hWinPause,TRUE xor ebx,ebx .while ! (dwOption & F_STOP) inc ebx invoke SetDlgItemInt,hWinMain,IDC_COUNTER,ebx,FALSE invoke WaitForSingleObject,hEvent,INFINITE .endw invoke SetWindowText,hWinCount,addr szStart invoke EnableWindow,hWinPause,FALSE and dwOption,not (F_COUNTING or F_STOP or F_PAUSE) ret _Counter endp ;#################################################################### _ProcDlgMain proc uses ebx edi esi hWnd,wMsg,wParam,lParam local @dwThreadID mov eax,wMsg ;******************************************************************** .if eax == WM_COMMAND mov eax,wParam .if ax == IDOK .if dwOption & F_COUNTING invoke SetEvent,hEvent or dwOption,F_STOP .else invoke CreateThread,NULL,0,\ offset _Counter,NULL,\ NULL,addr @dwThreadID invoke CloseHandle,eax .endif .elseif ax == IDC_PAUSE xor dwOption,F_PAUSE .if dwOption & F_PAUSE invoke ResetEvent,hEvent .else invoke SetEvent,hEvent .endif .endif ;******************************************************************** .elseif eax == WM_CLOSE invoke CloseHandle,hEvent invoke EndDialog,hWnd,NULL ;******************************************************************** .elseif eax == WM_INITDIALOG push hWnd pop hWinMain invoke GetDlgItem,hWnd,IDOK mov hWinCount,eax invoke GetDlgItem,hWnd,IDC_PAUSE mov hWinPause,eax invoke CreateEvent,NULL,TRUE,FALSE,NULL mov hEvent,eax ;******************************************************************** .else mov eax,FALSE ret .endif mov eax,TRUE ret _ProcDlgMain endp ;#################################################################### start: invoke GetModuleHandle,NULL mov hInstance,eax invoke DialogBoxParam,eax,DLG_MAIN,\ NULL,offset _ProcDlgMain,NULL invoke ExitProcess,NULL ;#################################################################### end start
修改以后编译执行,然后打开任务管理器观察程序的CPU占用率就可以发现,当按下 “暂停/恢复”按钮暂停计数后,程序的CPU占用率马上下降到接近零,再次按动按钮恢复计数时,CPU占用率会恢复到原来的数值,这说明程序的运行效率得到了很大的提高。
上页:第12章 多线程 · 12.3 使用事件对象控制线程(1) 下页:第12章 多线程 · 12.4 线程间的同步(1)
第12章 多线程
版权所有 © 云南伯恩科技 证书:粤ICP备09170368号