Windows編程之多線程事件對象(Event Object)用法詳解

目錄

一、前言

二、基礎用法

三、API詳解

1.創建事件對象

2控制事件狀態

3.等待事件對象:

四、實戰案例

1.案例描述?

2.代碼設計

?3.總設計代碼

4.運行結果


一、前言

????????事件對象(Event Object)是我們在大型項目中,進行多線程同步處理的時候經常用到的一種內核對象,下面我就根據它的基礎本身的特點和相關的API函數,與實戰案例相結合,講述它的基礎理論和用法。

二、基礎用法

????????在Windows編程中,事件對象(Event Objects)是一種內核對象,主要用于線程之間的同步。當多個進程需要訪問共享資源時,可以通過CreateEvent創建的事件對象來控制訪問順序,避免資源沖突和數據不一致的問題。

????????事件對象中經常結合進行使用的有以下四種api函數,我們掌握了這四種API函數的基本用法,可以說就掌握了事件對象(Event Object)。以下api函數分別為 CreateEvent ,?SetEvent,

ResetEvent ?WaitForSingleObject。后面我會依次講解各個api函數的原型以及作用。

三、API詳解

1.創建事件對象

? ? ? ? ? ?我們可以使用 CreateEven 函數來創建一個事件對象,它是一個Windows API函數,這個函數允許你指定事件對象的安全屬性、是手動重置還是自動重置、以及它的初始狀態(信號態或非信號態)。下面是它的原型:

HANDLE WINAPI CreateEventW(_In_opt_ LPSECURITY_ATTRIBUTES lpEventAttributes,   //安全屬性_In_ BOOL bManualReset,  // 復位方式:true 必須用 resetevent手動復原 false 自動還原為無信號狀態_In_ BOOL bInitialState,  //初始狀態 : true 初始狀態為有信號狀態: false 無信號狀態_In_opt_ LPCWSTR lpName    //對象名稱: null 無名的事件對象);

? ? ? ? 可以根據原型解釋,它的返回值類型為 句柄(空指針) ,函數約束類型為 WINAPI (_stdcall)

????????第一個參數為??lpEventAttributes ,也就是安全屬性,它是作為windows內核對象必須要有的參數類型。

????????第二個參數是指復位方式,如果為TRUE,則事件對象需要顯式調用ResetEvent函數來重置為無信號狀態;如果為FALSE,則事件對象在單個等待線程被釋放后自動重置為無信號狀態。

? ? ? ? 第三個參數為信號狀態也就是指定事件對象的初始狀態,如果為TRUE,則事件對象被創建時處于有信號狀態;如果為FALSE,則處于無信號狀態。

? ? ? ? 第四個參數為指定事件對象的名稱,通常為NULL,為無名的事件對象。

2控制事件狀態

????????事件對象有兩種狀態——發信號和不發信號。

???????SetEvent:將事件對象的狀態置為發信號狀態,允許等待該事件的線程繼續執行。

? ? ? ?ResetEvent:將事件對象的狀態置為不發信號狀態。

WINBASEAPI BOOL WINAPI SetEvent(_In_ HANDLE hEvent);WINBASEAPI BOOL WINAPI ResetEvent(_In_ HANDLE hEvent);

? ? ? ? 原型為上述代碼,參數都是為 HANDLE (句柄),也就是?CreateEven 函數的返回值,

3.等待事件對象

? ? ??使用 WaitForSingleObject 或 WaitForMultipleObjects?函數等待一個或多個事件對象變為信號態, 線程才會繼續向下執行。

? ? ? ? 函數原型如下,參數都大致相同。

WINBASEAPI DWORD WINAPI WaitForSingleObject(_In_ HANDLE hHandle,_In_ DWORD dwMilliseconds);

四、實戰案例

? ? ? ? 上面我們已經講述了事件對象的作用以及一些常用的api方法和屬性,下面我將會通過一個實際有代表性的案例來繼續講解事件對象,來加深它的用法和印象。

1.案例描述?

? ? ? ? 下面游樂園有兩個售票口 A 和?售票口 B,游樂園限制最多100人進,假設這兩個售票口所賣的是不同種類的票,一共有100張。那么該如何設計程序,保證售票口 A 和?售票口 B 同時所賣的票不是同一張票。

2.代碼設計

? ? ? ? 上述案例我們可以用編程的角度去分析問題和解決問題。

????????售票口 A 和?售票口 B 可以分別看作兩個線程,線程 A和線程 B。100張票可以當作全局變量,作為線程A,B需要訪問的公共資源。代碼設計為:

#include <stdio.h>
#include <windows.h>
#include <process.h>// 共享資源 (100張票)
int iTickets = 100;// 事件對象
HANDLE g_hEvent;int main()
{// 線程A 和 線程BHANDLE hThreadA, hThreadB;hThreadA = CreateThread(NULL, 0, SellTicketA, NULL, 0, 0);hThreadB = CreateThread(NULL, 0, SellTicketB, NULL, 0, 0);CloseHandle(hThreadA); CloseHandle(hThreadB);system("pause");return 0;
}

????????那么就只需要保證線程A 和 線程 B在同一時間只能對共享資源的單一訪問,這里我們就可以用到事件對象(Event Objects)。

    //手動重置 FALSE:設置無信號狀態,未觸發狀態g_hEvent = CreateEvent(NULL, FALSE, TRUE, NULL);SetEvent(g_hEvent);Sleep(4000);CloseHandle(g_hEvent);

????????具體做法為 進程A 可以通過 SetEvent函數 將事件對象的狀態設置為有信號狀態,進程B 則可以通 WaitForSingleObject 等函數等待該事件對象變為有信號狀態,從而實現進程間的信號傳遞和協調,代碼為:

    while (1){WaitForSingleObject(g_hEvent, INFINITE);if (iTickets > 0){Sleep(1);iTickets--;printf("A remain %d\n",iTickets);}else{break;}SetEvent(g_hEvent);}return 0;
?3.總設計代碼

? ? ? ? 以下是設計的總代碼:

#include <stdio.h>
#include <windows.h>
#include <process.h>// 共享資源 (100張票)
int iTickets = 100;// 事件對象
HANDLE g_hEvent;DWORD WINAPI SellTicketA(void* arg)
{while (1){WaitForSingleObject(g_hEvent, INFINITE);if (iTickets > 0){Sleep(1);iTickets--;printf("A remain %d\n",iTickets);}else{break;}SetEvent(g_hEvent);}return 0;
}
DWORD WINAPI SellTicketB(void* arg)
{while (1){WaitForSingleObject(g_hEvent, INFINITE);if (iTickets > 0){Sleep(1);iTickets--;printf("B remain %d\n", iTickets);}else{break;}SetEvent(g_hEvent);}return 0;
}int main()
{// 線程A 和 線程BHANDLE hThreadA, hThreadB;hThreadA = CreateThread(NULL, 0, SellTicketA, NULL, 0, 0);hThreadB = CreateThread(NULL, 0, SellTicketB, NULL, 0, 0);CloseHandle(hThreadA); CloseHandle(hThreadB);//手動重置 FALSE:設置無信號狀態,未觸發狀態g_hEvent = CreateEvent(NULL, FALSE, TRUE, NULL);SetEvent(g_hEvent);Sleep(4000);CloseHandle(g_hEvent);system("pause");return 0;
}
4.運行結果

? ? ? ? 代碼運行的總結果如下。

?

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/40385.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/40385.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/40385.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

競賽選題 醫學大數據分析 - 心血管疾病分析

文章目錄 1 前言1 課題背景2 數據處理3 數據可視化4 最后 1 前言 &#x1f525; 優質競賽項目系列&#xff0c;今天要分享的是 &#x1f6a9; 基于大數據的心血管疾病分析 該項目較為新穎&#xff0c;適合作為競賽課題方向&#xff0c;學長非常推薦&#xff01; &#x1f9…

AI繪畫Stable Diffusion 解鎖精美壁紙創作:利用SD與LLM定制你的專屬壁紙,AI副業變現指南!

大家好&#xff0c;我是畫畫的小強 今天給大家分享一下用AI繪畫Stable Diffusion 制作精美手機壁紙&#xff0c;這也可能是當前最快AIGC變現的一種途徑。雖然本文的主題為手機壁紙&#xff0c;當調整不同的比例的分辨率寬高比例&#xff0c;就可以直接復用到手機、電腦和平板、…

旋轉和鏡像的關系

旋轉矩陣行列式與 在E(3)三維空間中&#xff0c;旋轉矩陣的行列式可以用來判斷該旋轉是否包含鏡像變換。 行列式為正&#xff1a; 表示純旋轉&#xff0c;不包含鏡像。 旋轉矩陣保持向量的長度和角度不變&#xff0c;只是改變向量的方向。 行列式為負&#xff1a; 表示旋轉…

機器學習原理之 -- 支持向量機分類:由來及原理詳解

支持向量機&#xff08;Support Vector Machine, SVM&#xff09;是統計學習理論的一個重要成果&#xff0c;廣泛應用于分類和回歸問題。SVM以其高效的分類性能和良好的泛化能力在機器學習領域中占據重要地位。本文將詳細介紹支持向量機的由來、基本原理、構建過程及其優缺點。…

LVS負載均衡群集部署之——DR模式的介紹及搭建步驟

一、LVS-DR集群介紹1.1 LVS-DR 工作原理1.2 數據包流向分析1.3 LVS-DR 模式的特點1.4 LVS-DR中的ARP問題1.4.1 問題一1.4.2 問題二二、構建LVS-DR集群2.1 構建LVS-DR集群的步驟&#xff08;理論&#xff09;1.配置負載調度器&#xff08;192.168.80.30&#xff09;&#xff08;…

5分鐘教你用AI把老照片動起來,別再去花49塊9的冤枉錢了

文章目錄 需要的工具 最近&#xff0c;AI視頻在各大平臺上&#xff0c;又火了。 只是火的形式&#xff0c;變成了將老照片動起來&#xff0c;打情感牌&#xff0c;或者做很多經典電視劇的再整活。 直接把可靈的生成時間&#xff0c;從以前的4分鐘&#xff0c;生生的干成了20分鐘…

鴻蒙應用筆記

安裝就跳過了&#xff0c;一直點點就可以了 配置跳過&#xff0c;就自動下了點東西。 鴻蒙那個下載要12g個內存&#xff0c;大的有點嚇人。 里面跟idea沒區別 模擬器或者真機運行 真機要鴻蒙4.0&#xff0c;就可以實機調試 直接在手機里面跑&#xff0c;這個牛逼&#xf…

國標GB/T 28181詳解:國標GBT28181-2022 SIP服務器發起廣播的命令流程

目錄 一、定義 二、作用 1、實現信息的集中管理和分發 &#xff08;1&#xff09;信息集中 &#xff08;2&#xff09;信息分發 2、提高信息傳輸的可靠性和效率 &#xff08;1&#xff09;可靠性 &#xff08;2&#xff09;提高效率 3、支持多種設備和系統的互通 &am…

mongdb學習與使用

1. 基礎概念 MongoDB簡介&#xff1a; MongoDB是一個基于文檔的NoSQL數據庫&#xff0c;具有高性能、高可用性和易擴展性。數據存儲在類似JSON的BSON格式中。 基本術語&#xff1a; Database&#xff08;數據庫&#xff09;&#xff1a; 集合的容器。Collection&#xff08;集合…

國產強大免費WAF, 社區版雷池動態防護介紹

雷池WAF&#xff0c;基于智能語義分析的下一代 Web 應用防火墻 使用情況 我司于2023年4月23日對雷池進行測試&#xff0c;測試一個月后&#xff0c;于2023年5月24日對雷池進行正式切換&#xff0c;此時版本為1.5.1。 里程碑紀念 后續一直跟隨雷池進行版本升級&#xff0c;當前…

QT_GUI

1、QT安裝 一個跨平臺的應用程序和用戶界面框架&#xff0c;用于開發圖形用戶界面&#xff08;GUI&#xff09;應用程序以及命令行工具。QT有商業版額免費開源版&#xff0c;一般使用免費開源版即可&#xff0c;下面安裝的是QT5&#xff0c;因為出來較早&#xff0c;使用較多&…

Python特征工程 — 1.4 特征歸一化方法詳解

目錄 1 Min-Max歸一化 方法1&#xff1a;自定義的Min-Max歸一化封裝函數 方法2&#xff1a; scikit-learn庫中的MinMaxScaler 2 Z-score歸一化 方法1&#xff1a;自定義的Z-score歸一化封裝函數 方法2&#xff1a; scikit-learn庫中的StandardScaler 3 最大值歸一化 4 L…

考研生活day1--王道課后習題2.2.1、2.2.2、2.2.3

2.2.1 題目描述&#xff1a; 解題思路&#xff1a; 這是最基礎的操作&#xff0c;思路大家應該都有&#xff0c;缺少的應該是如何下筆&#xff0c;很多同學都是有思路但是不知道如何下筆&#xff0c;這時候看思路的意義不大&#xff0c;可以直接看答案怎么寫&#xff0c;最好…

Java項目:基于SSM框架實現的游戲攻略網站系統分前后臺【ssm+B/S架構+源碼+數據庫+畢業論文+任務書】

一、項目簡介 本項目是一套基于SSM框架實現的游戲攻略網站系統 包含&#xff1a;項目源碼、數據庫腳本等&#xff0c;該項目附帶全部源碼可作為畢設使用。 項目都經過嚴格調試&#xff0c;eclipse或者idea 確保可以運行&#xff01; 該系統功能完善、界面美觀、操作簡單、功能…

redhat7.x 升級openssh至openssh-9.8p1

1.環境準備&#xff1a; OS系統&#xff1a;redhat 7.4 2.備份配置文件&#xff1a; cp -rf /etc/ssh /etc/ssh.bak cp -rf /usr/bin/openssl /usr/bin/openssl.bak cp -rf /etc/pam.d /etc/pam.d.bak cp -rf /usr/lib/systemd/system /usr/lib/systemd/system.bak 3.安裝…

UB9A0全系統全頻高精度板卡性能指標

UB9A0 板卡是基于和芯星通自主研發的新一代射頻基帶及高精度算法一體化 GNSS SoC 芯片—Nebulas Ⅳ開發的全系統全頻點高精 OEM 板卡 &#xff0c;支持 BDS&#xff0c;GPS&#xff0c; GLONASS&#xff0c;Galileo&#xff0c;QZSS&#xff0c;NavIC&#xff0c;SBAS&#xff…

linux c 應用編程定時器函數

在 Linux C 應用編程中&#xff0c;對于多線程編程中的定時器函數使用&#xff0c;通常可以借助 pthread 庫和系統提供的定時器相關的函數來實現。 首先&#xff0c;常見的定時器函數有 setitimer() 和 alarm() 。setitimer() 函數可以更精確地設置定時器&#xff0c;它可以設…

JAVA學習-練習試用Java實現“螺旋矩陣 II”

問題&#xff1a; 給定一個正整數 n &#xff0c;生成一個包含 1 到 n2 所有元素&#xff0c;且元素按順時針順序螺旋排列的 n x n 正方形矩陣 matrix 。 示例 1&#xff1a; 輸入&#xff1a;n 3 輸出&#xff1a;[[1,2,3],[8,9,4],[7,6,5]] 示例 2&#xff1a; 輸入&…

C++標準模板(STL)- 迭代器庫 - 流迭代器- 寫入 std::basic_streambuf 的輸出迭代器(二)

迭代器庫-流迭代器 迭代器庫提供了五種迭代器的定義&#xff0c;同時還提供了迭代器特征、適配器及相關的工具函數。 迭代器分類 迭代器共有五 (C17 前)六 (C17 起)種&#xff1a;遺留輸入迭代器 (LegacyInputIterator) 、遺留輸出迭代器 (LegacyOutputIterator) 、遺留向前迭代…

MySQL環境搭配

下載版本37滴 下載第二個 之后進行安裝 進入安裝界面 next 選擇默認的 進行下一步 安裝成功后&#xff0c;進行一系列配置&#xff0c;成功界面如下&#xff1a; 配置 MySQL8.0 環境變量 如果不配置 MySQL 環境變量&#xff0c;就不能在命令行直接輸入 MySQL 登錄命令。 步…