专业编程基础技术教程

网站首页 > 基础教程 正文

C#中AutoResetEvent和ManualResetEvent使用场景

ccvgpt 2024-08-28 13:36:33 基础教程 12 ℃

AutoResetEvent和ManualResetEvent是.NET Framework中用于同步多线程操作的两个非常重要的类。它们都属于System.Threading命名空间,主要用于在多个线程之间实现信号量或互斥锁的功能。本文将深入探讨这两个类的知识和原理,并给出必要的实例和使用场景。

AutoResetEvent

AutoResetEvent是一个非阻塞的事件类,它允许一个或多个等待线程继续执行。当AutoResetEvent的Set方法被调用时,所有等待在该事件上的线程都将被唤醒。当AutoResetEvent的Reset方法被调用时,该事件将被重置,所有等待在该事件上的线程都将被阻止。

C#中AutoResetEvent和ManualResetEvent使用场景

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可以确保每个线程都按照预期的顺序执行关键部分的代码

Tags:

最近发表
标签列表