首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 組合語言

Win32 組合語言教程:事件對象實現執行緒同步

     編輯:組合語言

前言

多執行緒程式設計中,執行緒間同步是核心課題。Windows 提供事件對象作為輕量級同步機制,本質為雙態訊號(有訊號/無訊號),類似開關。本文說明事件對象建立、狀態控制、等待機制,並以 MASM 範例展示主執行緒透過選單啟動/停止工作執行緒的完整流程。

事件對象核心 API

CreateEvent

CreateEvent proto lpEventAttributes:DWORD,
                  bManualReset:DWORD,
                  bInitialState:DWORD,
                  lpName:DWORD
  • lpEventAttributes:NULL 使用預設安全屬性
  • bManualReset:FALSE=自動重設(WaitForSingleObject 返回後自動歸無訊號),TRUE=手動重設(需呼叫 ResetEvent)
  • bInitialState:TRUE=初始有訊號,FALSE=初始無訊號
  • lpName:跨程序共享時指定名稱,否則 NULL

成功返回事件控制碼,失敗返回 NULL。

狀態控制函式

  • SetEvent(hEvent):設為有訊號
  • ResetEvent(hEvent):設為無訊號(手動重設模式必須)

WaitForSingleObject

WaitForSingleObject proto hObject:DWORD, dwTimeout:DWORD
  • hObject:同步物件控制碼(事件、執行緒、處理程序等)
  • dwTimeout:等待毫秒數,INFINITE (0xFFFFFFFF) 表無限期等待

物件變為有訊號時函式返回,執行緒繼續執行;逾時則返回 WAIT_TIMEOUT。

範例程式:可啟動/停止的計算執行緒

主視窗提供「Run Thread」與「Stop Thread」選單項。啟動時建立自動重設、初始無訊號的事件,並創建工作執行緒;工作執行緒一進入即 WaitForSingleObject(hEventStart, INFINITE) 阻塞;使用者選「Run」呼叫 SetEvent 喚醒執行緒執行 6 億次加法運算;選「Stop」設全域旗標 EventStop=TRUE,執行緒檢測到後彈出訊息並跳回等待狀態。

關鍵程式碼片段

WM_CREATE:建立事件與執行緒

.IF uMsg==WM_CREATE
  invoke CreateEvent, NULL, FALSE, FALSE, NULL  ; 自動重設、初始無訊號
  mov hEventStart, eax
  mov eax, OFFSET ThreadProc
  invoke CreateThread, NULL, NULL, eax, NULL, 0, ADDR ThreadID
  invoke CloseHandle, eax        ; 不需執行緒控制碼,立即關閉避免洩漏

工作執行緒主體

ThreadProc PROC USES ecx Param:DWORD
  invoke WaitForSingleObject, hEventStart, INFINITE
  mov ecx, 600000000
  .WHILE ecx!=0
    .if EventStop!=TRUE
      add eax, eax
      dec ecx
    .else
      invoke MessageBox, hwnd, ADDR StopString, ADDR AppName, MB_OK
      mov EventStop, FALSE
      jmp ThreadProc            ; 重新進入等待
    .endif
  .ENDW
  invoke PostMessage, hwnd, WM_FINISH, NULL, NULL
  invoke EnableMenuItem, hMenu, IDM_START_THREAD, MF_ENABLED
  invoke EnableMenuItem, hMenu, IDM_STOP_THREAD, MF_GRAYED
  jmp ThreadProc                ; 循環等待下一次啟動
  ret
ThreadProc ENDP

選單命令處理

.ELSEIF uMsg==WM_COMMAND
  mov eax, wParam
  .if lParam==0
    .if ax==IDM_START_THREAD
      invoke SetEvent, hEventStart
      invoke EnableMenuItem, hMenu, IDM_START_THREAD, MF_GRAYED
      invoke EnableMenuItem, hMenu, IDM_STOP_THREAD, MF_ENABLED
    .elseif ax==IDM_STOP_THREAD
      mov EventStop, TRUE
      invoke EnableMenuItem, hMenu, IDM_START_THREAD, MF_ENABLED
      invoke EnableMenuItem, hMenu, IDM_STOP_THREAD, MF_GRAYED
    .else
      invoke DestroyWindow, hWnd
    .endif
  .endif

設計重點解析

  1. 自動重設事件:bManualReset=FALSE 免去手動 ResetEvent,每次 WaitForSingleObject 返回自動歸無訊號,適合「單次觸發、單次消費」模型。
  2. 執行緒生命週期管理:工作執行緒不結束,改以迴圈 jmp ThreadProc 重複等待→執行→等待,避免頻繁建立/銷毀開銷。
  3. 全域旗標配合事件:事件負責「啟動」,布林旗標 EventStop 負責「中斷」,兩者分工明確。
  4. 關閉執行緒控制碼:CreateThread 返回的控制碼若不需 WaitForSingleObject 等待執行緒結束,應立即 CloseHandle 釋放核心物件參考計數。

總結

事件對象提供簡潔高效的執行緒同步原語。掌握 CreateEvent 參數含義、自動/手動重設差異、WaitForSingleObject 等待語意,結合全域旗標實現複雜控制邏輯,是 Win32 多執行緒程式設計的基本功。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved