C#多線程之線程通訊(AutoResetEvent)
一、簡(jiǎn)介
我們?cè)诰€程編程的時(shí)候往往會(huì)涉及到線程的通信,通過(guò)信號(hào)的接受來(lái)進(jìn)行線程是否阻塞的操作。
AutoResetEvent 允許線程通過(guò)發(fā)信號(hào)互相通信。通常,此通信涉及線程需要獨(dú)占訪問(wèn)的資源。具體方法和擴(kuò)展方法請(qǐng)?jiān)斠?jiàn)AutoResetEvent類,最常用方法中就有Set()和WaitOne()。
線程通過(guò)調(diào)用 AutoResetEvent 上的 WaitOne 來(lái)等待信號(hào)。如果 AutoResetEvent 處于非終止?fàn)顟B(tài),則該線程阻塞,并等待當(dāng)前控制資源的線程通過(guò)調(diào)用 Set 發(fā)出資源可用的信號(hào)。AutoResetEvent 的非終止?fàn)顟B(tài)可以通過(guò)構(gòu)造函數(shù)在設(shè)置。
通俗的來(lái)講只有等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í)行,但是卻無(wú)法知道它什么時(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é)果:

上面例子中一開(kāi)始非終止?fàn)顟B(tài),當(dāng)遇到WaitOne()方法時(shí)則會(huì)阻塞線程,在沒(méi)有set()時(shí)將一直處于阻塞狀態(tài).
三、總結(jié)
既然說(shuō)到了AutoResetEvent,就不得不說(shuō)ManualResetEvent,這兩個(gè)方法幾乎相同,不同的地方就在于AutoResetEvent的WaitOne()方法執(zhí)行后會(huì)自動(dòng)又將信號(hào)置為不發(fā)送狀態(tài)也就是阻塞狀態(tài),當(dāng)再次遇到WaitOne()方法是又會(huì)被阻塞,而ManualResetEvent則不會(huì),只要線程處于非阻塞狀態(tài)則無(wú)論遇到多少次WaitOne()方法都不會(huì)被阻塞,除非調(diào)用ReSet()方法來(lái)手動(dòng)阻塞線程。
到此這篇關(guān)于C#多線程之線程通訊(AutoResetEvent)的文章就介紹到這了。希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
C#調(diào)用HTTP POST請(qǐng)求上傳圖片的示例代碼
現(xiàn)在很多B/S系統(tǒng)的開(kāi)發(fā)都是通過(guò)API方式來(lái)進(jìn)行的,一般服務(wù)端會(huì)開(kāi)放一個(gè)API接口,客戶端調(diào)用API接口來(lái)實(shí)現(xiàn)圖片或文件上傳的功能,感興趣的可以了解一下2021-05-05
C#動(dòng)態(tài)創(chuàng)建Access數(shù)據(jù)庫(kù)及密碼的方法
同為微軟的產(chǎn)品,本文將討論的是C#如何創(chuàng)建Access數(shù)據(jù)庫(kù),同時(shí)創(chuàng)建數(shù)據(jù)庫(kù)密碼與相關(guān)操作,希望對(duì)大家有所幫助。2015-09-09
使用C#實(shí)現(xiàn)網(wǎng)頁(yè)內(nèi)容保存為圖片并生成壓縮包
這篇文章主要為大家詳細(xì)介紹了如何使用C#實(shí)現(xiàn)網(wǎng)頁(yè)內(nèi)容保存為圖片并生成壓縮包,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2024-02-02
C#中窗體重復(fù)創(chuàng)建問(wèn)題的解決方法
在C#Windows窗體應(yīng)用中,我們經(jīng)常遇到這樣的問(wèn)題,當(dāng)我們觸發(fā)一個(gè)窗口命令時(shí),我連續(xù)點(diǎn)擊其中一個(gè)命令,會(huì)出現(xiàn)多個(gè)同樣的窗口,但我們是不管點(diǎn)擊多少次,都只出現(xiàn)一次,所以本文給大家介紹了C#中窗體重復(fù)創(chuàng)建問(wèn)題的解決方法,需要的朋友可以參考下2024-04-04
使用C# 調(diào)用deepseek api接口實(shí)現(xiàn)正常訪問(wèn)的過(guò)程
本文介紹了使用C#調(diào)用deepseek API接口實(shí)現(xiàn)正常訪問(wèn)的方法,包括解決SSL/TLS安全通道問(wèn)題和切換模型等常見(jiàn)問(wèn)題,并提供了默認(rèn)使用的reasoner模型和賬戶余額信息,感興趣的朋友一起看看吧2025-02-02
如何利用C#通過(guò)sql語(yǔ)句操作Sqlserver數(shù)據(jù)庫(kù)教程
ado.net提供了豐富的數(shù)據(jù)庫(kù)操作,下面這篇文章主要給大家介紹了關(guān)于如何利用C#通過(guò)sql語(yǔ)句操作Sqlserver數(shù)據(jù)庫(kù)教程的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-10-10
C#使用TreeView控件實(shí)現(xiàn)的二叉樹(shù)泛型節(jié)點(diǎn)類及其方法
TreeView?控件在?C#?中主要用于顯示分層結(jié)構(gòu)的數(shù)據(jù),這通常是一個(gè)文件系統(tǒng)的表示,但也可以是任何具有父子關(guān)系的數(shù)據(jù)集合,本文給大家介紹了C#使用TreeView控件實(shí)現(xiàn)的二叉樹(shù)泛型節(jié)點(diǎn)類及其方法,需要的朋友可以參考下2024-03-03
C#中調(diào)用Windows API的技術(shù)要點(diǎn)說(shuō)明
本篇文章主要是對(duì)C#中調(diào)用Windows API的技術(shù)要點(diǎn)進(jìn)行了詳細(xì)的介紹,需要的朋友可以過(guò)來(lái)參考下,希望對(duì)大家有所幫助2014-01-01

