魔诀 发表于 2014-7-22 14:24:52

多线程问题,求解。

32位汇编语言程序设计中的第12.4节中有个“问题程序”,这个问题程序是用多线程来计数的,这个程序本身要表达的关于线程同步的问题我能理解,但还有一个问题就是,这个程序编译执行后,不能正常退出。我把程序做了一点点的修改,如下(注释的地):
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
                .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_COUNTER1        equ        1001
IDC_COUNTER2        equ        1002
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 数据段
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
                .data?
hInstance        dd        ?
hWinMain        dd        ?
hWinCount        dd        ?
dwThreads        dd        ?

dwOption        dd        ?
F_STOP                equ        0001h

dwCounter1        dd        ?
dwCounter2        dd        ?

                .const
szStop                db        '停止计数',0
szStart                db        '计数',0
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 代码段
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

                .code
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_Counter        proc        uses ebx esi edi,_lParam

                inc        dwThreads
                invoke        SetDlgItemInt,hWinMain,IDC_COUNTER1,dwThreads,FALSE   ;加上的代码,用以显示创建的线程数
                invoke        SetWindowText,hWinCount,addr szStop
                and        dwOption,not F_STOP

                .while        ! (dwOption & F_STOP)
                        inc        dwCounter1
                        mov        eax,dwCounter2
                        inc        eax
                        mov        dwCounter2,eax
                .endw
               
                dec        dwThreads
                invoke        SetDlgItemInt,hWinMain,IDC_COUNTER2,dwThreads,FALSE   ;加上的代码,用以显示最后存留的线程数
                invoke        SetWindowText,hWinCount,addr szStart
                ret

_Counter        endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_ProcDlgMain        proc        uses ebx edi esi hWnd,wMsg,wParam,lParam
                local        @dwThreadID

                mov        eax,wMsg
;********************************************************************
                .if        eax ==        WM_TIMER
                        ;invoke        SetDlgItemInt,hWinMain,IDC_COUNTER1,dwCounter1,FALSE在代码前加了上注释符
                        ;invoke        SetDlgItemInt,hWinMain,IDC_COUNTER2,dwCounter2,FALSE   
;********************************************************************
                .elseif        eax ==        WM_COMMAND
                        mov        eax,wParam
                        .if        ax ==        IDOK
                                .if        dwThreads
                                        or        dwOption,F_STOP
                                        invoke        KillTimer,hWnd,1
                                       
                                .else
                                        mov        dwCounter1,0
                                        mov        dwCounter2,0
                                        xor        ebx,ebx
                                        .while        ebx <        10
                                                invoke        CreateThread,NULL,0,offset _Counter,NULL,\
                                                        NULL,addr @dwThreadID
                                                invoke        CloseHandle,eax
                                                inc        ebx
                                        .endw
                                        invoke        SetTimer,hWnd,1,500,NULL
                                .endif
                        .endif
;********************************************************************
                .elseif        eax ==        WM_CLOSE
                        .if        ! dwThreads
                                invoke        EndDialog,hWnd,NULL
                        .endif
;********************************************************************
                .elseif        eax ==        WM_INITDIALOG
                        push        hWnd
                        pop        hWinMain
                        invoke        GetDlgItem,hWnd,IDOK
                        mov        hWinCount,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
修改后编译执行程序,运行结果如图:
有线程在程序中存留,这应该就是程序无法正常退出的原因了。这也是我无法理解的地方 ,为什么会有线程存留?
dwOption的值被修改后,线程不是应该在被按排上时间片后结束的吗?
在课本的后续章节中,用事件对象对程序进行了修改,而我也对修改后的程序又做了如上的一点点变动,扫行结果如下:
                                                                                                                                                                                    多运行几次,也会有线程在程序中存留,但是在这儿程序却可以正常的结束,这又是为什么?




shehdok 发表于 2014-7-26 22:40:16

我都没学到这里
页: [1]
查看完整版本: 多线程问题,求解。