C#多线程之线程通讯(AutoResetEvent)
概述
在多线程中,线程之间的通讯是非常重要的一环。当一个线程处理完数据后,需要通知另一个线程来消费这个数据,这时候就需要线程通讯。C#中.NET框架提供两个线程通讯的类:
- EventWaitHandle (ManualResetEvent和AutoResetEvent)
- Monitor和lock
本文主要讲解AutoResetEvent的使用。
AutoResetEvent概述
AutoResetEvent是一种同步基元,它允许一个线程等待另一个线程发送信号。AutoResetEvent允许线程等待,并在信号到达时通知等待线程继续执行。
AutoResetEvent的用法类似于信号灯机制,最初状态为红灯(没通行权),当一个线程得到通行权,灯变为绿色(有通行权),其他的线程则处于等待。
AutoResetEvent的构造方法
public AutoResetEvent(bool initialState);
bool initialState参数用于确定AutoResetEvent对象的初始状态。如果是true,AutoResetEvent对象被创建时是终止状态(状态为绿色),如果是false,则是非终止状态(状态为红色)。
AutoResetEvent的方法
AutoResetEvent提供了以下3个方法:
- WaitOne() //阻止当前线程,直到当前WaitHandle收到信号。
- Set() //将事件状态设置为终止,允许一个或多个等待线程继续执行。
- Reset() //将事件状态设置为非终止,使一个或多个等待线程在继续执行前等待信号。
AutoResetEvent的使用示例
示例1:通过AutoResetEvent来交替输出奇偶数
class Program
{
private static AutoResetEvent odd = new AutoResetEvent(false); //奇数信号灯
private static AutoResetEvent even = new AutoResetEvent(false); //偶数信号灯
static void Main(string[] args)
{
Thread t1 = new Thread(PrintOdd); //奇数线程
Thread t2 = new Thread(PrintEven); //偶数线程
t1.Start();
t2.Start();
Console.ReadKey();
}
private static void PrintOdd()
{
for (int i = 1; i <= 9; i += 2)
{
Console.WriteLine("{0} at thread {1}", i, Thread.CurrentThread.ManagedThreadId);
even.Set(); //通知偶数线程可以执行了
odd.WaitOne(); //等待奇数线程的通知
}
}
private static void PrintEven()
{
for (int i = 2; i <= 10; i += 2)
{
even.WaitOne(); //等待偶数线程的通知
Console.WriteLine("{0} at thread {1}", i, Thread.CurrentThread.ManagedThreadId);
odd.Set(); //通知奇数线程可以执行了
}
}
}
示例2:通过AutoResetEvent来协调主线程和子线程
class Program
{
private static AutoResetEvent arEvent = new AutoResetEvent(false);
static void Main(string[] args)
{
Thread t = new Thread(() =>
{
Console.WriteLine("Son thread is running...");
Thread.Sleep(2000);
arEvent.Set(); //让主线程接着执行
Console.WriteLine("Son thread is finishing...");
});
t.Start();
Console.WriteLine("Main thread is waiting for son thread to complete...");
arEvent.WaitOne(); //等待子线程执行完毕
Console.WriteLine("Main thread is done with son thread.");
}
}
注意事项
AutoResetEvent的Set()方法是将状态改为“有通行权”,并不会检查是否有其他处于等待状态的线程,需要开发者把握调用时机,否则会因线程等待而导致死锁。
AutoResetEvent没有计数器的概念,也就是说,调用了Set()方法后,只有一个等待中的线程可以被唤醒,因此,AutoResetEvent适合用于只有两个线程交替执行的场景,如示例1所示。如果需要多个等待线程一起执行,应该使用ManualResetEvent。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C#多线程之线程通讯(AutoResetEvent) - Python技术站