C#中多線程ManualResetEvent 與 AutoResetEvent 區(qū)別
在多線程開發(fā)中,時(shí)常用到ManualResetEvent 與AutoResetEvent 。 它們?nèi)缤缆方煌ㄖ械男盘?hào)燈。兩者之間有什么區(qū)別呢?
共同點(diǎn):
均繼承EventWaitHandle 接口,因此,均具有以下功能:
Reset() //紅燈
Set() //綠燈
WaitOne() // 等待信號(hào)
不同點(diǎn):
AutoResetEvent 收到 Set 后 , 一次只能執(zhí)行一個(gè)線程,其它線程繼續(xù) WaitOne 。
ManualResetEvent 收到 Set 后,所有處理 WaitOne 狀態(tài)線程均繼續(xù)執(zhí)行。
msdn 提到(如果沒有線程 處于WaitOne() 狀態(tài),而調(diào)用 Set ,AutoResetEvent將保持Set 狀態(tài)):
調(diào)用Set信號(hào)AutoResetEvent釋放等待線程。 AutoResetEvent 將保持終止?fàn)顟B(tài)直到一個(gè)等待線程釋放,并自動(dòng)返回到非信號(hào)狀態(tài)。 如果沒有線程處于等待狀態(tài),狀態(tài)將無限期地保持已發(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è)線程。 如果兩次調(diào)用太靠近在一起,以便第二次調(diào)用前釋放線程發(fā)生,只有一個(gè)線程被釋放。 就像第二次調(diào)用未發(fā)生。 此外,如果Set時(shí)沒有等待的線程調(diào)用和AutoResetEvent已終止,則調(diào)用不起作用。
有網(wǎng)友說:
AutoResetEvent.Set() = ManualResetEvent.Set() + ManualResetEvent.Reset();
個(gè)人理解 ,這只是原理層面含義,實(shí)際使用過程中,有差別的,如下示例:
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è)線程喚起執(zhí)行,無法預(yù)料:
需要加鎖 ,確保一次通過一個(gè)線程:
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# Split分隔字符串的應(yīng)用(C#、split、分隔、字符串)
C# Split分隔字符串主要包括用字符串分隔,用多個(gè)字符來分隔,用單個(gè)字符來分隔等方法實(shí)現(xiàn),下面的具體的實(shí)現(xiàn)代碼2008-11-11C# UDP網(wǎng)絡(luò)通信的實(shí)現(xiàn)示例
UDP協(xié)議是互聯(lián)網(wǎng)上使用最廣泛的傳輸協(xié)議之一,具有簡(jiǎn)單、高效和不可靠的特點(diǎn),本文主要介紹了C# UDP網(wǎng)絡(luò)通信的實(shí)現(xiàn)示例,具有一定的參考價(jià)值,感興趣的可以了解一下2024-06-06C#使用文件流FileStream和內(nèi)存流MemoryStream操作底層字節(jié)數(shù)組byte[]
這篇文章介紹了C#使用文件流FileStream和內(nèi)存流MemoryStream操作底層字節(jié)數(shù)組byte[]的方法,文中通過示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-05-05在Framework 4.0中:找出新增的方法與新增的類(一)
經(jīng)常看到有同學(xué)在討論Framework 4 的新特性,新方法,于是想寫個(gè)程序找出framework4.0中新增的方法和類2013-05-05