网站首页 > 技术文章 正文
AutoResetEvent和ManualResetEvent是.NET Framework中用于同步多线程操作的两个非常重要的类。它们都属于System.Threading命名空间,主要用于在多个线程之间实现信号量或互斥锁的功能。本文将深入探讨这两个类的知识和原理,并给出必要的实例和使用场景。
AutoResetEvent
AutoResetEvent是一个非阻塞的事件类,它允许一个或多个等待线程继续执行。当AutoResetEvent的Set方法被调用时,所有等待在该事件上的线程都将被唤醒。当AutoResetEvent的Reset方法被调用时,该事件将被重置,所有等待在该事件上的线程都将被阻止。
AutoResetEvent的主要优点是它不会阻止调用线程,因为它是非阻塞的。这意味着在调用Set或Reset方法时,不需要使用锁来保护事件对象。
实例:
static AutoResetEvent autoEvent = new AutoResetEvent(false);
static void Main()
{
Thread thread1 = new Thread(DoWork);
thread1.Start();
Console.WriteLine("主线程等待子线程完成...");
autoEvent.WaitOne(); // 等待子线程完成
Console.WriteLine("子线程已完成,主线程继续执行。");
}
static void DoWork()
{
Console.WriteLine("子线程开始工作...");
Thread.Sleep(2000); // 模拟耗时操作
Console.WriteLine("子线程工作完成。");
autoEvent.Set(); // 设置事件,唤醒等待的线程
}
运行结果:
使用场景:AutoResetEvent适用于需要多个线程同时执行的场景,例如生产者-消费者模型、任务队列等。在这些场景中,AutoResetEvent可以确保只有一个线程在执行关键部分的代码,而其他线程则在等待信号。
ManualResetEvent
ManualResetEvent是一个阻塞的事件类,它允许一个或多个等待线程继续执行。与AutoResetEvent不同,ManualResetEvent需要手动重置才能使等待的线程继续执行。当ManualResetEvent的Set方法被调用时,所有等待在该事件上的线程都将被唤醒。多个线程可以通过调用ManualResetEvent对象的WaitOne方法进入等待或阻塞状态。当控制线程调用Set()方法,所有等待线程将恢复并继续执行。
ManualResetEvent的主要优点是它可以更好地控制线程的执行顺序。通过手动重置事件,可以实现更复杂的同步逻辑。
实例:
class Program
{
static void Main()
{
ManualResetEvent manualEvent = new ManualResetEvent(false);
int threadCount = 5;
Thread[] threads = new Thread[threadCount];
Console.WriteLine("{0} 主线程开始Set。", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
for (int i = 0; i < threadCount; i++)
{
threads[i] = new Thread(DoWork);
threads[i].Start(manualEvent);
}
manualEvent.Set();
manualEvent.Reset();
Console.WriteLine();
Thread.Sleep(2000);
manualEvent.Set();
for (int i = 0; i < threadCount; i++)
{
threads[i].Join(); // 等待所有线程完成
}
Console.WriteLine("所有线程已完成。");
}
static void DoWork(object state)
{
var manualEvent = (ManualResetEvent)state;
Console.WriteLine("{0} 线程 {1} 收到事件,开始执行任务1。", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), Thread.CurrentThread.ManagedThreadId);
manualEvent.WaitOne();
Console.WriteLine("{0} 线程 {1} 收到事件,开始执行任务2。", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), Thread.CurrentThread.ManagedThreadId);
manualEvent.WaitOne();
}
}
运行结果:
使用场景:ManualResetEvent适用于需要多个线程按照特定顺序执行的场景,例如任务链、并行处理等。在这些场景中,ManualResetEvent可以确保每个线程都按照预期的顺序执行关键部分的代码
猜你喜欢
- 2024-09-11 C# (Winform)实现USB HID自定义接口操作(控制下位机,如STM32)
- 2024-09-11 Tcp服务端一直sleep,客户端不断发送数据产生的问题
- 2024-09-11 C#中的进程与线程及其并发编程(c#多线程并发处理)
- 2024-09-11 在服务中默默地执行C#业务代码(在服务中默默地执行c#业务代码)
- 2024-09-11 C# AutoResetEvent 和 ManualResetEvent 在 WinForms 应用中的使用
- 2024-09-11 C#基础 DateTime详解(c# datetime.date)
- 2024-09-11 C# 面向对象 静态类和静态成员(c# 静态方法和实例方法)
- 2024-09-11 C#编程中如何使用线程(c#线程是什么)
- 2024-09-11 一篇文章搞懂C#中的接口(c#中接口怎么使用)
- 2024-09-11 C#高精度Timer和Delay以及时间测量
- 最近发表
- 标签列表
-
- cmd/c (57)
- c++中::是什么意思 (57)
- sqlset (59)
- ps可以打开pdf格式吗 (58)
- phprequire_once (61)
- localstorage.removeitem (74)
- routermode (59)
- vector线程安全吗 (70)
- & (66)
- java (73)
- org.redisson (64)
- log.warn (60)
- cannotinstantiatethetype (62)
- js数组插入 (83)
- resttemplateokhttp (59)
- gormwherein (64)
- linux删除一个文件夹 (65)
- mac安装java (72)
- reader.onload (61)
- outofmemoryerror是什么意思 (64)
- flask文件上传 (63)
- eacces (67)
- 查看mysql是否启动 (70)
- java是值传递还是引用传递 (58)
- 无效的列索引 (74)