知识问答

C#中ManualResetEvent用法详解

以下是关于“C#中ManualResetEvent用法详解”的完整攻略。

概述

ManualResetEvent 是一个同步基元,它允许一个或多个线程等待信号,然后再继续执行。当 WaitOne 方法被调用时,会阻塞线程直到接收到信号,然后线程被唤醒并继续执行。

ManualResetEvent 主要由两个方法 WaitOne() 和 Set() 组成。WaitOne() 方法用于阻塞等待,在没有接收到信号时,它会一直阻塞。Set() 方法用于发送信号,当 ManualResetEvent 接收到信号后,WaitOne() 方法将会返回。

应用实例

示例一 - 多线程控制

ManualResetEvent 可以用于多线程控制,示例代码如下:

class Program{    static ManualResetEvent manualResetEvent = new ManualResetEvent(false);    static int count = 5;    static void Main(string[] args)    {        Thread thread1 = new Thread(DoWork);        Thread thread2 = new Thread(DoWork);        thread1.Start();        thread2.Start();        Console.Read();    }    static void DoWork()    {        Interlocked.Decrement(ref count);        if (count == 0)        {            manualResetEvent.Set();            Console.WriteLine("All threads have done their work.");        }        Console.WriteLine("Thread {0} has done its work.", Thread.CurrentThread.ManagedThreadId);        manualResetEvent.WaitOne();        Console.WriteLine("Thread {0} has resumed.", Thread.CurrentThread.ManagedThreadId);    }}

在这个例子中,我们创建了一个 ManualResetEvent 对象,用于控制两个线程的执行过程。在代码的开头,我们设置了一个计数器 count 的值为 5。在 DoWork 方法中,首先使用了 Interlocked.Decrement() 方法对 count 进行自减操作。然后,IF 判断语句会判断当前计数器的值是否为 0。如果计数器的值为 0,则通过 manualResetEvent.Set() 方法设置 ManualResetEvent 的信号,此时 WaitOne() 方法的阻塞状态会被解除,并继续向下执行。否则,当线程等待信号时,WaitOne() 方法将会阻塞线程,直到计数器变为 0 并手动设置 ManualResetEvent 的信号。

示例二 - 异步编程

ManualResetEvent 还可以用于异步编程中,可以在异步方法完成时设置 ManualResetEvent 的信号,以便通知等待该异步方法完成的代码。示例代码如下:

class Program{    static void Main(string[] args)    {        Console.WriteLine("Starting Async operation");        ManualResetEvent manualResetEvent = new ManualResetEvent(false);        WebClient client = new WebClient();        client.DownloadStringCompleted += (s, e) =>        {            Console.WriteLine("Done! Result is: {0}", e.Result);            manualResetEvent.Set();        };        client.DownloadStringAsync(new Uri("https://www.baidu.com"));        manualResetEvent.WaitOne();        Console.WriteLine("Async Operation completed");        Console.ReadLine();    }}

在这个例子中,我们使用 .NET 内置的 WebClient 访问百度页面,并在访问完成时设置 ManualResetEvent 的信号来通知等待线程。在异步回调函数中,调用 Set() 方法以通知主线程等待的任务已经完成了。然后主线程等待该信号,直到下载请求完成后设置信号 WaitForSingleObject()。