WIN32汇编语言教程:第12章 多线程 · 12.2 多线程编程(1)

12.2.1 一个单线程的“问题程序”

来看一个“问题程序”,假设编写一个计数程序,程序的要求如下:

● 界面如图12.1所示,用对话框做主界面,对话框中放置“计数”按钮和“暂停/恢复”按钮,并有一个编辑框用来显示计数结果。

● 开始计数之前,“暂停/恢复”按钮处于灰化状态,当开始计数后,该按钮被激活,用户按动一次这个按钮,则计数暂停,再一次按动,则继续计数。

● 开始计数后,“计数”按钮上的文字将被改为“停止计数”,如果按下“停止计数”按钮,程序将恢复初始状态——第一个按钮变回“计数”按钮,同时灰化“暂停/恢复”按钮。


图12.1 一个有问题的计数程序

程序的代码在所附光盘的Chapter12\Counter目录中,里面的Counter.rc文件定义了图12.1所示的对话框,其代码如下:

//##################################################################
#include             <resource.h>
//##################################################################
#define ICO_MAIN                  1000
#define DLG_MAIN                  1000
#define IDC_COUNTER           1001
#define IDC_PAUSE            1002
//##################################################################
ICO_MAIN      ICON             "Main.ico"
//##################################################################
DLG_MAIN DIALOG 227, 187, 129, 48
STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
CAPTION "“问题程序”——计数器"
FONT 9, "宋体"
{
 LTEXT "计数值:", -1, 10, 10, 34, 8
 EDITTEXT IDC_COUNTER, 47, 8, 71, 12, ES_READONLY | WS_BORDER | WS_TABSTOP
 PUSHBUTTON "计数", IDOK, 8, 27, 50, 14
 PUSHBUTTON "暂停/恢复", IDC_PAUSE, 68, 27, 50, 14, WS_DISABLED | WS_TABSTOP
}
//##################################################################

汇编源文件写起来似乎很简单,只要在WM_COMMAND消息中对“计数”和“暂停/恢复”按钮的动作进行处理就可以了。在“计数”按钮中,可以调用一个计数子程序不停地进行加法运算并将结果显示出来,为了能够随时停止或暂停,可以设置一个标志位,按动“停止计数”或者“暂停/恢复”按钮时设置不同的标志,计数子程序在循环中通过测试这个标志位来决定是否暂停或退出。按照这个思路,程序可以写成目录中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    ?
 
dwOption          dd    ?          ;标志位
F_PAUSE       equ    0001h      ;暂停标志
F_STOP       equ    0002h      ;停止标志
F_COUNTING    equ    0004h      ;计算中标志
                .const
szStop         db     '停止计数',0
szStart        db     '计数',0
;####################################################################
; 代码段
;####################################################################
                 .code
;####################################################################
_Counter          proc
 
                or    dwOption,F_COUNTING
                and    dwOption,not (F_STOP or F_PAUSE)
                 invoke SetWindowText,hWinCount,addr szStop
                invoke EnableWindow,hWinPause,TRUE
 
                 xor ebx,ebx
                 .while ! (dwOption & F_STOP)
                         .if    !(dwOption & F_PAUSE)
                                 inc    ebx
                                 invoke SetDlgItemInt,hWinMain,\
                                         IDC_COUNTER,ebx,FALSE
                       .endif
                 .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
                                 or    dwOption,F_STOP
                       .else
                                 call   _Counter
                         .endif
                 .elseif ax ==  IDC_PAUSE
                         xor dwOption,F_PAUSE
                 .endif
;********************************************************************
             .elseif eax == WM_CLOSE
                     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
;********************************************************************
             .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

上页:第12章 多线程 · 12.1 进程和线程 下页:第12章 多线程 · 12.2 多线程编程(2)

第12章 多线程

版权所有 © 云南伯恩科技 证书:粤ICP备09170368号