C#多线程之线程同步WaitHandle
在C#多线程编程中,当多个线程同时访问同一个资源时,就要用到线程同步技术。WaitHandle就是其中一种线程同步机制。本文将详细讲解WaitHandle的用法。
什么是WaitHandle
WaitHandle是一个抽象基类,定义了等待时的信号通知方式。它有两个主要的实现类:AutoResetEvent和ManualResetEvent。这两个类都继承自WaitHandle类,实现了不同的信号通知方式。
AutoResetEvent是一种自动重置的信号通知方式,当一个线程等待AutoResetEvent时,它会等待直到其他线程调用Set方法,这时AutoResetEvent会发出一个信号通知正在等待的线程,唤醒一个线程继续执行。当一个线程被唤醒时,AutoResetEvent会自动重置,下一个等待的线程仍需等待其他线程再次调用Set方法才能唤醒。
ManualResetEvent是一种手动重置的信号通知方式,当一个线程等待ManualResetEvent时,它会等待直到其他线程调用Set方法,这时ManualResetEvent会发出一个信号通知正在等待的线程,唤醒一个线程继续执行。当一个线程被唤醒时,ManualResetEvent不会自动重置,下一个等待的线程可以直接通过,如果需要让ManualResetEvent重新等待,则需要其他线程再次调用Reset方法。
WaitHandle的用法
使用WaitHandle的主要步骤如下:
- 创建一个WaitHandle对象,可以使用AutoResetEvent或ManualResetEvent;
- 等待方式为阻塞方式;
- 设置信号时使用Set方法;
- 重置信号时使用Reset方法。
以下示例说明WaitHandle的用法:
示例1
在下面的示例中,多个线程访问一个共享的资源count,并同步使用AutoResetEvent来保护共享资源。线程A和线程B通过轮流递增count的方式演示了AutoResetEvent自动重置的特点。
class Program
{
private static int count = 0;
private static AutoResetEvent autoEvent = new AutoResetEvent(false);
static void Main(string[] args)
{
Thread threadA = new Thread(() =>
{
while (true)
{
Thread.Sleep(1000);
Interlocked.Increment(ref count);
Console.WriteLine("Thread A adds count to {0}", count);
autoEvent.Set();
}
});
Thread threadB = new Thread(() =>
{
while (true)
{
autoEvent.WaitOne();
Interlocked.Increment(ref count);
Console.WriteLine("Thread B adds count to {0}", count);
}
});
threadA.Start();
threadB.Start();
}
}
示例2
在下面的示例中,多个线程访问一个共享的资源count,并同步使用ManualResetEvent来保护共享资源。线程A和线程B通过轮流递增count的方式演示了ManualResetEvent手动重置的特点。
class Program
{
private static int count = 0;
private static ManualResetEvent manualEvent = new ManualResetEvent(false);
static void Main(string[] args)
{
Thread threadA = new Thread(() =>
{
while (true)
{
Thread.Sleep(1000);
Interlocked.Increment(ref count);
Console.WriteLine("Thread A adds count to {0}", count);
manualEvent.Set();
}
});
Thread threadB = new Thread(() =>
{
while (true)
{
manualEvent.WaitOne();
Interlocked.Increment(ref count);
Console.WriteLine("Thread B adds count to {0}", count);
manualEvent.Reset();
}
});
threadA.Start();
threadB.Start();
}
}
在以上两个示例中,使用WaitOne方法阻塞线程来等待信号的设置,使用Set方法设置信号,使用Reset方法重置信号。线程A不断增加count的值并设置信号,线程B阻塞等待信号,并在收到信号后递增count的值,演示了WaitHandle的使用方法。
总结
WaitHandle提供了一种线程同步的机制,可以保护共享的资源。AutoResetEvent和ManualResetEvent是WaitHandle的两个重要实现类,分别提供了自动重置和手动重置的信号通知方式。在使用WaitHandle时需要注意,在设置信号时只唤醒一个等待线程,并不会保证唤醒的线程就是先前等待最久的线程。使用WaitHandle需要合理设计线程的启动和停止方式,以保证线程的正常运行。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C#多线程之线程同步WaitHandle - Python技术站