C#中多線(xiàn)程ManualResetEvent 與 AutoResetEvent 區(qū)別
在多線(xiàn)程開(kāi)發(fā)中,時(shí)常用到ManualResetEvent 與AutoResetEvent 。 它們?nèi)缤缆方煌ㄖ械男盘?hào)燈。兩者之間有什么區(qū)別呢?
共同點(diǎn):
均繼承EventWaitHandle 接口,因此,均具有以下功能:
Reset() //紅燈
Set() //綠燈
WaitOne() // 等待信號(hào)
不同點(diǎn):
AutoResetEvent 收到 Set 后 , 一次只能執(zhí)行一個(gè)線(xiàn)程,其它線(xiàn)程繼續(xù) WaitOne 。
ManualResetEvent 收到 Set 后,所有處理 WaitOne 狀態(tài)線(xiàn)程均繼續(xù)執(zhí)行。
msdn 提到(如果沒(méi)有線(xiàn)程 處于WaitOne() 狀態(tài),而調(diào)用 Set ,AutoResetEvent將保持Set 狀態(tài)):
調(diào)用Set信號(hào)AutoResetEvent釋放等待線(xiàn)程。 AutoResetEvent 將保持終止?fàn)顟B(tài)直到一個(gè)等待線(xiàn)程釋放,并自動(dòng)返回到非信號(hào)狀態(tài)。 如果沒(méi)有線(xiàn)程處于等待狀態(tài),狀態(tài)將無(wú)限期地保持已發(fā)出信號(hào)。
因此通常WatiOne 之前,先 Reset() 一下,清除Set 信號(hào)
需要注意的是(兩個(gè) Set 調(diào)用之間時(shí)間較短,第二個(gè) Set 信號(hào)可能會(huì)丟失,因此連續(xù) Set 調(diào)用,中間需要 Sleep 一定時(shí)間):
不能保證的每個(gè)調(diào)用Set方法將釋放一個(gè)線(xiàn)程。 如果兩次調(diào)用太靠近在一起,以便第二次調(diào)用前釋放線(xiàn)程發(fā)生,只有一個(gè)線(xiàn)程被釋放。 就像第二次調(diào)用未發(fā)生。 此外,如果Set時(shí)沒(méi)有等待的線(xiàn)程調(diào)用和AutoResetEvent已終止,則調(diào)用不起作用。
有網(wǎng)友說(shuō):
AutoResetEvent.Set() = ManualResetEvent.Set() + ManualResetEvent.Reset();
個(gè)人理解 ,這只是原理層面含義,實(shí)際使用過(guò)程中,有差別的,如下示例:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace testManualResetEvent
{
class Program
{
static object objManualResetEvent = new object();
static System.Threading.ManualResetEvent manu = new System.Threading.ManualResetEvent(false);
//static System.Threading.AutoResetEvent manu = new System.Threading.AutoResetEvent(false);
static void Main(string[] args)
{
for (int i = 0; i < 10; i++)
{
System.Threading.Thread t = new System.Threading.Thread(new System.Threading.ThreadStart(() => { Product(); }));
t.Start();
}
manu.Set();
manu.Reset();
Console.ReadKey();
}
static void Product()
{
manu.WaitOne(10000);
Console.WriteLine(System.Threading.Thread.CurrentThread.ManagedThreadId);
}
}
}
實(shí)際執(zhí)行結(jié)果 , 在 執(zhí)行 set 后 reset 前 ,有多少個(gè)線(xiàn)程喚起執(zhí)行,無(wú)法預(yù)料:

需要加鎖 ,確保一次通過(guò)一個(gè)線(xiàn)程:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace testManualResetEvent
{
class Program
{
static object objManualResetEvent = new object();
static System.Threading.ManualResetEvent manu = new System.Threading.ManualResetEvent(false);
//static System.Threading.AutoResetEvent manu = new System.Threading.AutoResetEvent(false);
static void Main(string[] args)
{
for (int i = 0; i < 10; i++)
{
System.Threading.Thread t = new System.Threading.Thread(new System.Threading.ThreadStart(() => { Product(); }));
t.Start();
}
manu.Set();
//System.Threading.Thread.Sleep(100); //連續(xù) set 需要 sleep
//manu.Set();
//manu.Reset();
//System.Threading.Thread.Sleep(100);
//manu.Set();
//manu.Reset();
Console.ReadKey();
}
static void Product()
{
lock (objManualResetEvent)
{
manu.WaitOne(10000); manu.Reset();
Console.WriteLine(System.Threading.Thread.CurrentThread.ManagedThreadId);
}
}
}
}
執(zhí)行結(jié)果:

到此這篇關(guān)于C#中ManualResetEvent 與 AutoResetEvent 區(qū)別的文章就介紹到這了,更多相關(guān)C#中ManualResetEvent AutoResetEvent 內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C#和SQL實(shí)現(xiàn)的字符串相似度計(jì)算代碼分享
這篇文章主要介紹了C#和SQL實(shí)現(xiàn)的字符串相似度計(jì)算代碼分享,本文分別給出了C#語(yǔ)言和SQL語(yǔ)言的實(shí)現(xiàn)代碼,需要的朋友可以參考下2014-10-10
C#文件斷點(diǎn)續(xù)傳實(shí)現(xiàn)方法
這篇文章主要介紹了C#文件斷點(diǎn)續(xù)傳實(shí)現(xiàn)方法,涉及C#文件傳輸?shù)募记?具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-08-08
C# 中 WebSocket 與 SignalR實(shí)時(shí)通信的兩種方案
在現(xiàn)代 Web 應(yīng)用中,實(shí)時(shí)通信變得越來(lái)越重要,無(wú)論是聊天應(yīng)用、在線(xiàn)游戲、股票行情推送還是協(xié)作編輯工具,都需要服務(wù)器能夠主動(dòng)向客戶(hù)端推送數(shù)據(jù),本文將對(duì)這兩種技術(shù)進(jìn)行比較,分析它們的異同點(diǎn)和使用場(chǎng)景,并提供簡(jiǎn)單示例代碼幫助你快速上手,感興趣的朋友一起看看吧2025-05-05
C#中的文件路徑獲取函數(shù)和文件名字獲取函數(shù)小結(jié)
這篇文章主要介紹了C#中的文件路徑獲取函數(shù)和文件名字獲取函數(shù)小結(jié),本文講解了獲取絕對(duì)文件路徑、獲取文件名字、獲得包含 path 目錄信等內(nèi)容,需要的朋友可以參考下2015-01-01
C# 獲取當(dāng)前月份天數(shù)的三種方法總結(jié)
本篇文章主要是對(duì)C#中獲取目前月份的天數(shù)的三種方法進(jìn)行了詳細(xì)的總結(jié)介紹,需要的朋友可以過(guò)來(lái)參考下,希望對(duì)大家有所幫助2014-01-01

