C#多線程之線程通訊(AutoResetEvent)
一、簡(jiǎn)介
我們?cè)诰€程編程的時(shí)候往往會(huì)涉及到線程的通信,通過信號(hào)的接受來進(jìn)行線程是否阻塞的操作。
AutoResetEvent 允許線程通過發(fā)信號(hào)互相通信。通常,此通信涉及線程需要獨(dú)占訪問的資源。具體方法和擴(kuò)展方法請(qǐng)?jiān)斠夾utoResetEvent類,最常用方法中就有Set()和WaitOne()。
線程通過調(diào)用 AutoResetEvent 上的 WaitOne 來等待信號(hào)。如果 AutoResetEvent 處于非終止?fàn)顟B(tài),則該線程阻塞,并等待當(dāng)前控制資源的線程通過調(diào)用 Set 發(fā)出資源可用的信號(hào)。AutoResetEvent 的非終止?fàn)顟B(tài)可以通過構(gòu)造函數(shù)在設(shè)置。
通俗的來講只有等myResetEven.Set()成功運(yùn)行后,myResetEven.WaitOne()才能夠獲得運(yùn)行機(jī)會(huì);Set是發(fā)信號(hào),WaitOne是等待信號(hào),只有發(fā)了信號(hào),
等待的才會(huì)執(zhí)行。如果不發(fā)的話,WaitOne后面的程序就永遠(yuǎn)不會(huì)執(zhí)行。
AutoResetEvent myEvent = new AutoResetEvent(false);
這里構(gòu)造函數(shù)中的參數(shù)false就代表該狀態(tài)為非終止?fàn)顟B(tài),相反若為true則為終止?fàn)顟B(tài)。
二、代碼
案例一:
public class Program { const int cycleNum = 10;static void Main(string[] args) { // 參數(shù): // workerThreads: // 要由線程池根據(jù)需要?jiǎng)?chuàng)建的新的最小工作程序線程數(shù)。 // completionPortThreads: // 要由線程池根據(jù)需要?jiǎng)?chuàng)建的新的最小空閑異步 I/O 線程數(shù)。 // 返回結(jié)果:如果更改成功,則為 true;否則為 false。 //public static bool SetMinThreads(int workerThreads, int completionPortThreads); ThreadPool.SetMinThreads(1, 1); // 參數(shù): // workerThreads: // 線程池中輔助線程的最大數(shù)目。 // completionPortThreads: // 線程池中異步 I/O 線程的最大數(shù)目。 // 返回結(jié)果:如果更改成功,則為 true;否則為 false。 //public static bool SetMaxThreads(int workerThreads, int completionPortThreads); ThreadPool.SetMaxThreads(5, 5); for (int i = 1; i <= cycleNum; i++) { ThreadPool.QueueUserWorkItem(new WaitCallback(testFun), i.ToString()); } Console.WriteLine("主線程執(zhí)行!"); Console.WriteLine("主線程終止!"); Console.WriteLine("線程池終止!"); Console.ReadKey(); } public static void testFun(object obj) { Console.WriteLine(string.Format("{0}:第{1}個(gè)線程", DateTime.Now.ToString(), obj.ToString())); Thread.Sleep(5000); } }
運(yùn)行結(jié)果:
這里可以看出,線程池里線程的執(zhí)行不影響主線程的運(yùn)行,線程池雖然可以管理多線程的執(zhí)行,但是卻無法知道它什么時(shí)候終止。
案例二:
public class Program { const int cycleNum = 10; static int cnt = 10; static AutoResetEvent myEvent = new AutoResetEvent(false); static void Main(string[] args) { // 參數(shù): // workerThreads: // 要由線程池根據(jù)需要?jiǎng)?chuàng)建的新的最小工作程序線程數(shù)。 // completionPortThreads: // 要由線程池根據(jù)需要?jiǎng)?chuàng)建的新的最小空閑異步 I/O 線程數(shù)。 // 返回結(jié)果:如果更改成功,則為 true;否則為 false。 //public static bool SetMinThreads(int workerThreads, int completionPortThreads); ThreadPool.SetMinThreads(1, 1); // 參數(shù): // workerThreads: // 線程池中輔助線程的最大數(shù)目。 // completionPortThreads: // 線程池中異步 I/O 線程的最大數(shù)目。 // 返回結(jié)果:如果更改成功,則為 true;否則為 false。 //public static bool SetMaxThreads(int workerThreads, int completionPortThreads); ThreadPool.SetMaxThreads(5, 5); for (int i = 1; i <= cycleNum; i++) { ThreadPool.QueueUserWorkItem(new WaitCallback(testFun), i.ToString()); } Console.WriteLine("主線程執(zhí)行!"); Console.WriteLine("主線程終止!"); myEvent.WaitOne(); Console.WriteLine("線程池終止!"); Console.ReadKey(); } public static void testFun(object obj) { cnt -= 1;//信號(hào)量自減 Console.WriteLine(string.Format("{0}:第{1}個(gè)線程", DateTime.Now.ToString(), obj.ToString())); Thread.Sleep(5000); if (cnt == 0) { myEvent.Set(); } } }
運(yùn)行結(jié)果:
上面例子中一開始非終止?fàn)顟B(tài),當(dāng)遇到WaitOne()方法時(shí)則會(huì)阻塞線程,在沒有set()時(shí)將一直處于阻塞狀態(tài).
三、總結(jié)
既然說到了AutoResetEvent,就不得不說ManualResetEvent,這兩個(gè)方法幾乎相同,不同的地方就在于AutoResetEvent的WaitOne()方法執(zhí)行后會(huì)自動(dòng)又將信號(hào)置為不發(fā)送狀態(tài)也就是阻塞狀態(tài),當(dāng)再次遇到WaitOne()方法是又會(huì)被阻塞,而ManualResetEvent則不會(huì),只要線程處于非阻塞狀態(tài)則無論遇到多少次WaitOne()方法都不會(huì)被阻塞,除非調(diào)用ReSet()方法來手動(dòng)阻塞線程。
到此這篇關(guān)于C#多線程之線程通訊(AutoResetEvent)的文章就介紹到這了。希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
C#通過經(jīng)緯度計(jì)算2個(gè)點(diǎn)之間距離的實(shí)現(xiàn)代碼
這篇文章主要介紹了C#通過經(jīng)緯度計(jì)算2個(gè)點(diǎn)之間距離實(shí)現(xiàn)代碼,本文對(duì)實(shí)現(xiàn)原理、經(jīng)緯度基本知識(shí)等一并做了講解,需要的朋友可以參考下2014-08-08DataTable的AcceptChanges()和RejectChanges()方法介紹并實(shí)現(xiàn)DataGridView
這篇文章介紹了DataTable的AcceptChanges()和RejectChanges()方法并實(shí)現(xiàn)DataGridView數(shù)據(jù)增、刪、改,文中通過示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-02-02C#小程序15位轉(zhuǎn)18位身份證號(hào)代碼
現(xiàn)在我們使用的都是18位身份證號(hào),而以前都是15位身份證號(hào),而如何將15位身份證號(hào)轉(zhuǎn)18位身份證號(hào)轉(zhuǎn)換為18位身份證號(hào)呢?2013-02-02利用C#實(shí)現(xiàn)網(wǎng)絡(luò)爬蟲
這篇文章主要介紹了利用C#實(shí)現(xiàn)網(wǎng)絡(luò)爬蟲,完整的介紹了C#實(shí)現(xiàn)網(wǎng)絡(luò)爬蟲詳細(xì)過程,感興趣的小伙伴們可以參考一下2016-03-03Unity實(shí)現(xiàn)物體運(yùn)動(dòng)時(shí)畫出軌跡
這篇文章主要為大家詳細(xì)介紹了Unity實(shí)現(xiàn)物體運(yùn)動(dòng)時(shí)畫出軌跡,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-09-09C#多線程編程之使用ReaderWriterLock類實(shí)現(xiàn)多用戶讀與單用戶寫同步的方法
這篇文章主要介紹了C#多線程編程之使用ReaderWriterLock類實(shí)現(xiàn)多用戶讀與單用戶寫同步的方法,涉及C#多線程操作讀寫鎖定的相關(guān)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-11-11C# 中 TryParse如何將字符串轉(zhuǎn)換為特定類型
在 C# 中,TryParse 是一個(gè)用于將字符串轉(zhuǎn)換為特定類型的方法,它用于嘗試解析字符串并將其轉(zhuǎn)換為指定類型的值,而不會(huì)引發(fā)異常,這篇文章主要介紹了C# 中 TryParse 將字符串轉(zhuǎn)換為特定類型的方法,需要的朋友可以參考下2024-03-03Unity3D UI Text得分?jǐn)?shù)字增加的實(shí)例代碼
這篇文章主要介紹了Unity3D UI Text得分?jǐn)?shù)字增加方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2021-04-04