Win32汇编系列八,多线程

前言

我对Windows线程API有一种恐怖的感觉,那是因为在以前第一次接触它的时候是通过VB,好吧,就是VB,在他的开发环境中做子类化或者多线程编程时,IDE总会莫名其妙经常崩溃,以至于后面继续是哪怕改了一个字符,运行时都要先保存一下,因为这个IDE可没有自动保存功能。

但说回来,并不是API恐怖,而是IDE恐怖。

CreateThread

见名知意,这是创建线程的函数,如果函数成功,则返回新线程的句柄。

HANDLE CreateThread(
  LPSECURITY_ATTRIBUTES   lpThreadAttributes,
  SIZE_T                  dwStackSize,
  LPTHREAD_START_ROUTINE  lpStartAddress,
  __drv_aliasesMem LPVOID lpParameter,
  DWORD                   dwCreationFlags,
  LPDWORD                 lpThreadId
);

参数介绍:

  1. lpThreadAttributes
    指向SECURITY_ATTRIBUTES 结构,表示线程内核对象的安全属性,一般传入NULL就行,表示使用默认设置。
  2. dwStackSize
    线程栈空间大小。传入0表示使用默认大小。
  3. lpStartAddress
    线程执行的函数地址,就是线程跑的代码段在哪个函数中。
  4. lpParameter
    线程函数的参数
  5. dwCreationFlags
    这个参数为0表示线程创建后马上就可以进行调度,如果为CREATE_SUSPENDED则表示线程创建后暂停运行,直到调用ResumeThread()。
  6. lpThreadId
    用于获取返回的线程的ID,传入NULL表示不需要返回该线程ID号。

还有两个创建线程的函数是_beginthread()或_beginthreadex(),自行了解一下。

代码示例

我们知道在做一个耗时较长的任务时,需要开启新线程,否则会阻塞后面代码执行,引起界面未响应。

下面简单做一个示例,开启一个线程,这个线程每隔1秒打印一次,一共打印5次。

.386 
.model flat,stdcall 
option casemap:none 
include c:\masm32\include\windows.inc 
include c:\masm32\include\user32.inc 
includelib c:\masm32\lib\user32.lib           
include c:\masm32\include\kernel32.inc 
includelib c:\masm32\lib\kernel32.lib 

include  c:\masm32\include\msvcrt.inc
includelib c:\masm32\lib\msvcrt.lib

WinMain proto :DWORD

.DATA                   
ClassName db "MyWindowClass",0       
AppName db "Win32线程",0    
ButtonClassName db "Button",0   
ButtonTitle db "开启线程",0
HelloGUI db "HelloGUI",0

Message db "完成",0
MessageTitle db "提示",0

OutMessage db "第%d次"
.DATA?              
hInstance HINSTANCE ?
hWindowHdc HDC ?
hButton HWND ?
hWindow HWND ?

ThreadID DWORD ? 
.CONST 
ButtonID equ 1 
.CODE             


start: 

invoke GetModuleHandle, NULL   
mov hInstance,eax 
invoke WinMain, hInstance
invoke ExitProcess, eax       
WinMain proc hInst:HINSTANCE
    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  hInstance 
    pop   wc.hInstance 
    mov   wc.hbrBackground,COLOR_WINDOW+1 
    mov   wc.lpszMenuName,NULL 
    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,NULL,\ 
                ADDR ClassName,\ 
                ADDR AppName,\ 
                WS_OVERLAPPEDWINDOW,\ 
                0,\ 
                0,\ 
                300,\ 
                300,\ 
                NULL,\ 
                NULL,\ 
                hInst,\ 
                NULL 
    mov   hWindow,eax

    invoke CreateWindowEx,NULL,ADDR ButtonClassName,ADDR ButtonTitle, WS_TABSTOP OR  WS_VISIBLE OR WS_CHILD OR BS_DEFPUSHBUTTON  ,\
    0,0,100,100,hWindow,ButtonID,NULL,NULL
    mov hButton,eax

    invoke GetDC,eax
    mov  hWindowHdc,eax
    invoke ShowWindow, hWindow,SW_SHOWDEFAULT   
    invoke UpdateWindow, hWindow               

    .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 

PrintThread proc num:dword
	invoke crt_printf, addr OutMessage,num
	.while num>0
		sub num,1
		invoke Sleep,1000
		invoke crt_printf, addr OutMessage,num
		  
	.endw	
	invoke MessageBox,NULL,addr Message,addr MessageTitle,MB_OK
	ret

PrintThread endp

WndProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM 
		LOCAL strRect:RECT
		.IF uMsg == WM_LBUTTONDOWN
			mov strRect.right,100
			mov strRect.bottom,100
			mov strRect.left,0
			mov strRect.top,0
			invoke DrawText,hWindowHdc, ADDR HelloGUI,8,ADDR  strRect,DT_VCENTER
		.ELSEIF uMsg ==WM_COMMAND
				mov eax,wParam 
				.IF ax == ButtonID 
				  mov  eax,OFFSET PrintThread 
            
                	invoke CreateThread,NULL,NULL,eax,5,0,ADDR ThreadID 
                	invoke CloseHandle,eax 

				.ENDIF
				
		.ELSE
			invoke DefWindowProc,hWnd,uMsg,wParam,lParam  
			ret
		.ENDIF
    ret 
WndProc endp 

end start 

如果在主线程开启循环打印的话,窗口就会无法拖动,但如果在新线程执行的话,窗口就可以拖动了。

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值