这篇文章主要介绍了C#怎么实现线程通知的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇C#怎么实现线程通知文章都会有所收获,下面我们一起来看看吧。

AutoRestEvent 类用于从一个线程向另一个线程发送通知。

微软文档是这样介绍的:表示线程同步事件在一个等待线程释放后收到信号时自动重置。

其构造函数只有一个:

构造函数里面的参数用于设置信号状态。

构造函数说明AutoResetEvent(Boolean)用一个指示是否将初始状态设置为终止的布尔值初始化 AutoResetEvent 类的新实例。

真糟糕的机器翻译。

常用方法

AutoRestEvent 类是干嘛的,构造函数的参数又是干嘛的?不着急,我们来先来看看这个类常用的方法:

方法说明Close()释放由当前 WaitHandle 占用的所有资源。Reset()将事件状态设置为非终止,从而导致线程受阻。Set()将事件状态设置为有信号,从而允许一个或多个等待线程继续执行。WaitOne()阻止当前线程,直到当前 WaitHandle 收到信号。WaitOne(Int32)阻止当前线程,直到当前 WaitHandle 收到信号,同时使用 32 位带符号整数指定时间间隔(以毫秒为单位)。WaitOne(Int32, Boolean)阻止当前线程,直到当前的 WaitHandle 收到信号为止,同时使用 32 位带符号整数指定时间间隔,并指定是否在等待之前退出同步域。WaitOne(TimeSpan)阻止当前线程,直到当前实例收到信号,同时使用 TimeSpan 指定时间间隔。WaitOne(TimeSpan, Boolean)阻止当前线程,直到当前实例收到信号为止,同时使用 TimeSpan 指定时间间隔,并指定是否在等待之前退出同步域。一个简单的示例

这里我们编写一个这样的程序:

创建一个线程,能够执行多个阶段的任务;每完成一个阶段,都需要停下来,等待子线程发生通知,才能继续下一步执行。

.WaitOne()用来等待另一个线程发送通知;

.Set()用来对线程发出通知,此时AutoResetEvent变成终止状态;

.ReSet()用来重置AutoResetEvent状态;

classProgram{//线程通知privatestaticAutoResetEventresetEvent=newAutoResetEvent(false);staticvoidMain(string[]args){//创建线程newThread(DoOne).Start();//用于不断向另一个线程发送信号while(true){Console.ReadKey();resetEvent.Set();//发生通知,设置终止状态}}publicstaticvoidDoOne(){Console.WriteLine("等待中,请发出信号允许我运行");//等待其它线程发送信号resetEvent.WaitOne();Console.WriteLine("\n收到信号,继续执行");for(inti=0;i<5;i++)Thread.Sleep(TimeSpan.FromSeconds(0.5));resetEvent.Reset();//重置为非终止状态Console.WriteLine("\n第一阶段运行完毕,请继续给予指示");//等待其它线程发送信号resetEvent.WaitOne();Console.WriteLine("\n收到信号,继续执行");for(inti=0;i<5;i++)Thread.Sleep(TimeSpan.FromSeconds(0.5));Console.WriteLine("\n第二阶段运行完毕,线程结束,请手动关闭窗口");}}解释一下

AutoResetEvent 对象有终止和非终止状态。Set()设置终止状态,Reset()重置非终止状态。

这个终止状态,可以理解成信号已经通知;非终止状态则是信号还没有通知。

注意,注意终止状态和非终止状态指的是 AutoResetEvent 的状态,不是指线程的状态。

线程通过调用 WaitOne() 方法,等待信号;
另一个线程可以调用 Set() 通知 AutoResetEvent 释放等待线程。
然后 AutoResetEvent 变为终止状态。

需要注意的是,如果 AutoResetEvent 已经处于终止状态,那么线程调用WaitOne()不会再起作用。除非调用Reset()

构造函数中的参数,正是设置这个状态的。true 代表终止状态,false 代表非终止状态。如果使用new AutoResetEvent(true);,则线程一开始是无需等待信号的。

在使用完类型后,您应直接或间接释放类型,显式调用Close()/Dispose()或 使用using。 当然,也可以直接退出程序。

需要注意的是,如果多次调用Set()的时间间隔过短,如果第一次Set()还没有结束(信号发送需要处理时间),那么第二次Set()可能无效(不起作用)。

复杂一点的示例

我们设计一个程序:

Two 线程开始处于阻塞状态;

线程 One 可以设置线程 Two 继续运行,然后阻塞自己;

线程 Two 可以设置 One 继续运行,然后阻塞自己;

程序代码如下(运行后,请将键盘设置成英文输入状态再按下按键):

classProgram{//控制第一个线程//第一个线程开始时,AutoResetEvent处于终止状态,无需等待信号privatestaticAutoResetEventoneResetEvent=newAutoResetEvent(true);//控制第二个线程//第二个线程开始时,AutoResetEvent处于非终止状态,需要等待信号privatestaticAutoResetEventtwoResetEvent=newAutoResetEvent(false);staticvoidMain(string[]args){newThread(DoOne).Start();newThread(DoTwo).Start();Console.ReadKey();}publicstaticvoidDoOne(){while(true){Console.WriteLine("\n①按一下键,我就让DoTwo运行");Console.ReadKey();twoResetEvent.Set();oneResetEvent.Reset();//等待DoTwo()给我信号oneResetEvent.WaitOne();Console.ForegroundColor=ConsoleColor.Green;Console.WriteLine("\nDoOne()执行");Console.ForegroundColor=ConsoleColor.White;}}publicstaticvoidDoTwo(){while(true){Thread.Sleep(TimeSpan.FromSeconds(1));//等待DoOne()给我信号twoResetEvent.WaitOne();Console.ForegroundColor=ConsoleColor.Yellow;Console.WriteLine("\nDoTwo()执行");Console.ForegroundColor=ConsoleColor.White;Console.WriteLine("\n②按一下键,我就让DoOne运行");Console.ReadKey();oneResetEvent.Set();twoResetEvent.Reset();}}}

解释

两个线程具有的功能:阻塞自己、解除另一个线程的阻塞。

用电影《最佳拍档》里面的一个画面来理解。

DoOne 、DoTwo 轮流呼吸,不能自己控制自己呼吸,但自己能够决定别人呼吸。

你搞我,我搞你,就能相互呼吸了。

当然WaitOne()也可以设置等待时间,如果 光头佬(DoOne) 耍赖不让 金刚(DoTwo)呼吸,金刚等待一定时间后,可以强行荡动天平,落地呼吸。

注意,AutoRestEvent 用得不当容易发生死锁。
另外 AutoRestEvent 使用的是内核时间模式,因此等待时间不能太长,不然比较耗费 CPU 时间。

AutoResetEvent 也适合用于线程同步。

另外,线程中使用WaitOne(),另一个线程使用Set()通知后, AutoResetEvent 对象会自动恢复非终止状态,不需要线程使用Reset()

关于“C#怎么实现线程通知”这篇文章的内容就介绍到这里,感谢各位的阅读!相信大家对“C#怎么实现线程通知”知识都有一定的了解,大家如果还想学习更多知识,欢迎关注亿速云行业资讯频道。