C# 的 ManualResetEvent(線程同步操作) 類詳解

C# 的 ManualResetEvent 類詳解

作用

ManualResetEvent?是用于線程同步操作的類,允許一個或多個線程等待特定信號,以協調多個線程的執行順序。它通過事件通知機制實現,確保線程在收到信號前保持阻塞,直到其他線程顯式發出信號。

核心功能
  • 阻塞線程:調用?WaitOne()?使線程進入等待狀態。

  • 發送信號:調用?Set()?將事件設為終止狀態,釋放所有等待線程。

  • 重置信號:調用?Reset()?將事件恢復為非終止狀態。


信號狀態:
  • 終止狀態:所有調用?WaitOne(),線程不會被阻塞,直到調用Reset()。
  • 非終止狀態:所有調用?WaitOne(),線程會被阻塞,直到調用set()。

特點
  1. 手動重置:調用?Set()?后需手動調用?Reset()?才能將狀態恢復為非終止狀態。

  2. 多線程釋放:一旦處于終止狀態(Signaled),所有等待線程立即釋放,直到手動重置。

  3. 線程安全:所有方法(SetResetWaitOne)都是線程安全的。

  4. 跨進程支持:可通過命名方式在進程間同步(構造函數傳名稱)。


應用場景
  1. 初始化同步:主線程等待子線程完成初始化后再繼續。

  2. 資源就緒通知:多個工作線程等待某個共享資源(如數據加載完成)。

  3. 階段化任務:分階段任務中,后續階段需等待前一階段所有線程完成。

  4. 高并發控制:替代鎖機制,允許多個線程同時訪問資源(需配合?Reset())。


基礎用法
  1. 初始化:創建實例,參數指定初始狀態(true?為終止狀態)。

    ManualResetEvent mre = new ManualResetEvent(false); // 初始為非終止
  2. 阻塞線程:調用?WaitOne()

    mre.WaitOne(); // 阻塞,直到事件變為終止狀態
  3. 發送信號:調用?Set()

    mre.Set(); // 設置為終止狀態,釋放所有等待線程
  4. 重置信號:調用?Reset()

    mre.Reset(); // 恢復為非終止狀態


代碼實例

場景 1:主線程等待子線程完成

用途

主線程需要等待子線程完成某個任務后再繼續執行。例如:主線程啟動后臺任務后需等待其初始化完成,再執行后續操作。

代碼邏輯
class Example
{static ManualResetEvent mre = new ManualResetEvent(false);static void Main(){Console.WriteLine("主線程啟動工作線程。");Thread worker = new Thread(DoWork);worker.Start();Console.WriteLine("主線程等待信號...");mre.WaitOne(); // 阻塞主線程,直到子線程調用 Set()Console.WriteLine("主線程恢復執行。");}static void DoWork(){Console.WriteLine("工作線程執行任務...");Thread.Sleep(2000); // 模擬耗時操作mre.Set(); // 發送信號,喚醒主線程}
}
執行流程
  1. 主線程創建?ManualResetEvent?并初始化為非終止狀態 (false)。

  2. 主線程啟動子線程?DoWork

  3. 主線程調用?mre.WaitOne()?進入阻塞狀態。

  4. 子線程執行任務(模擬耗時操作),完成后調用?mre.Set(),將事件狀態設為終止。

  5. 主線程從?WaitOne()?處解除阻塞,繼續執行后續代碼。

輸出結果
主線程啟動工作線程。
主線程等待信號...
工作線程執行任務...
(等待 2 秒后)
主線程恢復執行。


場景 2:多個線程等待同一事件

用途

多個工作線程需要等待某個公共條件(如資源初始化完成)滿足后,才能同時開始工作。例如:多個線程需等待數據庫連接池初始化完成后才可執行查詢。

代碼邏輯
using System;
using System.Threading;class Example
{static ManualResetEvent mre = new ManualResetEvent(false);static void Main(){// 啟動 3 個工作線程for (int i = 0; i < 3; i++){new Thread(Worker).Start(i);}// 啟動初始化線程new Thread(Initialize).Start();}static void Initialize(){Console.WriteLine("初始化開始...");Thread.Sleep(3000);Console.WriteLine("初始化完成!");mre.Set(); // 通知所有等待線程}static void Worker(object id){Console.WriteLine($"線程 {id} 等待初始化...");mre.WaitOne(); // 阻塞,直到初始化線程調用 Set()Console.WriteLine($"線程 {id} 開始工作。");}
}
執行流程
  1. 主線程啟動 3 個工作線程和一個初始化線程。

  2. 每個工作線程調用?mre.WaitOne()?進入阻塞狀態,等待初始化完成。

  3. 初始化線程執行耗時操作(如加載配置),完成后調用?mre.Set()

  4. 所有等待的工作線程同時被喚醒,開始執行后續任務。

輸出結果
線程 0 等待初始化...
線程 1 等待初始化...
線程 2 等待初始化...
初始化開始...
(等待 3 秒后)
初始化完成!
線程 0 開始工作。
線程 1 開始工作。
線程 2 開始工作。


場景 3:重復使用 ManualResetEvent

用途

需要多次復用同一個?ManualResetEvent?實例,分階段同步多個任務。例如:分批次處理數據,每批任務完成后觸發下一批任務。

代碼邏輯
using System;
using System.Threading;class Example
{static ManualResetEvent mre = new ManualResetEvent(false);static void Main(){// 首次使用new Thread(() => Task("任務1")).Start();mre.WaitOne();mre.Reset(); // 重置為非終止狀態// 第二次使用new Thread(() => Task("任務2")).Start();mre.WaitOne();}static void Task(string name){Console.WriteLine($"{name} 進行中...");Thread.Sleep(1000);mre.Set();}
}
執行流程
  1. 主線程啟動第一個子線程執行?任務1

  2. 主線程調用?mre.WaitOne()?阻塞,等待?任務1?完成。

  3. 子線程?任務1?完成后調用?mre.Set(),主線程恢復執行。

  4. 主線程調用?mre.Reset()?將事件重置為非終止狀態。

  5. 主線程啟動第二個子線程執行?任務2,再次調用?mre.WaitOne()?阻塞。

  6. 子線程?任務2?完成后調用?mre.Set(),主線程恢復執行。

輸出結果
任務1 進行中...
(等待 1 秒后)
任務2 進行中...
(等待 1 秒后)

三個場景關鍵區別總結

場景核心目的ManualResetEvent 操作要點
主線程等待子線程單向等待子線程完成子線程完成時調用?Set()
多線程等待同一事件廣播式喚醒所有等待線程Set()?后無需立即?Reset()
重復使用事件對象分階段同步任務每次使用后需調用?Reset()?重置狀態

通過這三個場景,可以靈活掌握?ManualResetEvent?在不同線程同步需求中的使用技巧。

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

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

相關文章

小白學習:提示工程(什么是prompt)

課程鏈接 https://www.bilibili.com/video/BV1PX9iYQEry/?spm_id_from333.337.search-card.all.click 一 什么是提示工程 【提示工程】也叫【指令工程】 prompt就是給大模型發的指令&#xff0c;如“給我講個笑話” 懂得提示工程原理會帶來什么優勢 懂得原理 為什么有的指…

Docker Compose 之詳解(Detailed Explanation of Docker Compose)

Docker Compose 之詳解 當容器數量逐漸增多&#xff0c;你是否感到手忙腳亂&#xff1f;面對復雜的部署場景&#xff0c;是時候祭出神器Docker Compose了&#xff01;它能幫你優雅地管理多容器應用&#xff0c;一鍵啟動、停止所有服務&#xff0c;不再為復雜的手動操作焦頭爛額…

C語言 —— 此去經年夢浪蕩魂音 - 深入理解指針(卷一)

目錄 1. 內存和地址 2. 指針變量和地址 2.1 取地址操作符&#xff08;&&#xff09; 2.2 指針變量 2.3 解引用操作符 &#xff08;*&#xff09; 3. 指針的解引用 3.1 指針 - 整數 3.2 void* 指針 4. const修飾指針 4.1 const修飾變量 4.2 const修飾指針變量 5…

【AI】從頭到腳詳解如何創建部署Azure Web App的OpenAI項目

【AI】從頭到腳詳解如何創建部署Azure Web App的OpenAI項目 在Azure Web應用上,您可以使用Python的OpenAI包方便快捷地調用官方API,上傳您的訓練數據,并利用他們的算法進行處理。本教程提供了一個逐步指南,幫助您在Azure Web應用上部署您的OpenAI項目,涵蓋了從資源設置到…

機器視覺工程師紅外相機的選擇:紅外長波工業相機和短波紅外工業相機玄機大總結

紅外長波(LWIR)和短波(SWIR)工業相機在原理、應用場景和技術特點上有顯著差異。以下是它們的對比分析: 1. 波長范圍與成像原理 2. 技術特點 3. 典型應用場景 4. 優缺點對比 LWIR優勢: 無需光照,適用于完全黑暗環境。 直接反映物體溫度分布。 對煙霧、灰塵穿透能力強。…

uni-app學習筆記——自定義模板

一、流程 1.這是一個硬性的流程&#xff0c;只要按照如此程序化就可以實現 二、步驟 1.第一步 2.第二步 3.第三步 4.每一次新建頁面&#xff0c;都如第二步一樣&#xff1b;可以選擇自定義的模版&#xff08;vue3Setup——這是我自己的模版&#xff09;&#xff0c;第二步的…

DeepSeek模型本地化部署方案及Python實現

DeepSeek實在是太火了&#xff0c;雖然經過擴容和調整&#xff0c;但反應依舊不穩定&#xff0c;甚至小圓圈轉半天最后卻提示“服務器繁忙&#xff0c;請稍后再試。” 故此&#xff0c;本文通過講解在本地部署 DeepSeek并配合python代碼實現&#xff0c;讓你零成本搭建自己的AI…

Vue3計算屬性深度解析:經典場景與Vue2對比

一、計算屬性的核心價值 計算屬性&#xff08;Computed Properties&#xff09;是Vue響應式系統的核心特性之一&#xff0c;它通過依賴追蹤和緩存機制優雅地解決模板中復雜邏輯的問題。當我們需要基于現有響應式數據進行派生計算時&#xff0c;計算屬性總能保持高效的性能表現…

python-leetcode-刪除鏈表的倒數第 N 個結點

LCR 021. 刪除鏈表的倒數第 N 個結點 - 力扣&#xff08;LeetCode&#xff09; 可以使用雙指針方法來解決這個問題&#xff0c;這樣可以在一次遍歷內完成刪除操作&#xff0c;從而達到 O(n) 的時間復雜度。以下是 Python 代碼實現&#xff1a; 解題思路&#xff1a; 初始化快…

vue2的webpack(vue.config.js) 怎么使用請求轉發 devServer.proxy

首先用 express 搭建后端服務器&#xff0c;注意使用中間件解析json格式的請求體&#xff0c;才會獲取到 post 參數 app.use(express.json()); app.js const express require(express) const app express() app.use(express.json()); const port 3000app.post(/api/vue2, …

Linux:基本指令與內涵理解

1.文件操作指令 1.1 ls ls指令用于查看指定層級文件夾下的文件或文件夾 基本格式&#xff1a;ls (選項) (查看層級&#xff09; 其中選項處不寫就默認是顯示文件名&#xff0c;查看層級默認是當前層級 選項1&#xff1a; -l 作用&#xff1a;將查找文件的詳細信息顯示出來 我們…

SpaceSync智能排班:重構未來辦公空間的神經中樞

文心智能體平臺可免費使用DeepSeek 滿血版啦&#xff0c;使用DeepSeek模型創建并提交智能體&#xff0c;即有機會瓜分萬元獎金&#xff01;有這等好事還不快沖&#xff01; 文心智能體官網&#xff1a;文心智能體平臺AgentBuilder | 想象即現實 本片文章為作者參加文心智能體平…

flutter dio庫 源碼賞析

1. factory函數 //調用factory構造方法后&#xff0c;實際返回的是Dio的子類 Dio dio Dio();abstract class Dio {factory Dio([BaseOptions? options]) > createDio(options); } 2. CancelToken 作用:取消操作 CancelToken cancelToken CancelToken();//監聽取消 ca…

RGV調度算法

1、基于時間窗 https://wenku.baidu.com/view/470e9fd8b4360b4c2e3f5727a5e9856a57122693.html?_wkts_1741880736197&bdQuery%E7%8E%AF%E7%A9%BF%E8%B0%83%E5%BA%A6%E7%AE%97%E6%B3%95 2.2019年MathorCup高校數學建模挑戰賽B題 2019-mathorcupB題-環形穿梭機調度模型&a…

基于CATIA VBA與Python的自動化音樂生成技術對比研究

在工程軟件二次開發領域&#xff0c;CATIA 也可以許多另類的玩法。通過CATIA自帶的VBA可以演奏歌曲&#xff0c;但實際效果往往差強人意。為了進一步優化實際演奏效果&#xff0c;本文以自動生成林宥嘉《說謊》鋼琴前奏旋律為案例&#xff0c;探討兩種語言在多媒體控制領域的技…

最大數位置(信息學奧賽一本通-2038)

【題目描述】 輸入n個整數,存放在數組a[1]至a[n]中&#xff0c;輸出最大數所在位置(n≤1000)。 【輸入】 第一行&#xff0c;數的個數n; 第二行&#xff0c;n個正整數&#xff0c;每個數在232?1之內。 【輸出】 最大數所在位置。 【輸入樣例】 5 67 43 90 78 32 【輸出樣例】 …

【AIGC】OpenAI 集成 Langchain 操作實戰使用詳解

目錄 一、前言 二、前置準備 2.1 安裝 Langchain必須的依賴 2.1.1 python環境 2.1.2 langchain openai 環境 2.1.3 準備一個apikey 2.1.4 langchain 核心組件 三、Langchain 各組件使用 3.1 Chat models組件 3.1.1 Invocation 使用 3.1.1.1 結果解析 3.2 提示詞模板…

【C#學習筆記04】深入掌握C語言格式化輸出

引言 ??printf()??函數不僅可以將數據輸出到控制臺&#xff0c;還可以通過格式化字符串靈活地控制輸出的格式。??printf()???函數的使用規則&#xff0c;包括標志說明、字段寬度、轉換精度、長度修飾、轉換說明、轉義字符和返回結果等內容。 1. ??printf()??函數…

python-leetcode-定長子串中元音的最大數目

1456. 定長子串中元音的最大數目 - 力扣&#xff08;LeetCode&#xff09; 可以使用 滑動窗口 方法來解決這個問題。步驟如下&#xff1a; 初始化&#xff1a;計算前 k 個字符中元音字母的個數&#xff0c;作為初始窗口的值。滑動窗口&#xff1a;遍歷字符串&#xff0c;每次右…

藍橋真題講解

第一題 題目鏈接 0貪吃蛇長度 - 藍橋云課 題目解析 題意&#xff1a;數#個數和個數再加上首尾 代碼原理 略 代碼編寫 略 填空題技巧 眼看手數 當然并不是真的一個一個數&#xff0c;我們需要借助一些工具&#xff0c;不過各位小伙伴們放心&#xff0c;我們借助的工具…