下面就详细讲解一下C#中AutoResetEvent控制线程用法的完整攻略。
什么是AutoResetEvent?
AutoResetEvent是一个同步基元,也是用于多线程编程的一个重要之一,它用于协调多个线程之间的同步。AutoResetEvent主要有两个用途:
- 线程等待
- 线程信号
AutoResetEvent是系统提供的,可以定时地向操作系统CPU请求任务调度,同时在内部实现了同步对象,可以直接调用。在C#中,AutoResetEvent是System.Threading和System.Threading.AutoResetEvent命名空间中的类型,可以用于多线程编程。
AutoResetEvent的操作
在使用AutoResetEvent时,一般会涉及两个操作:WaitOne()和Set()。意义分别如下:
- WaitOne():等待信号,该方法可以让线程等待其他线程发送的信号;
- Set():发送信号,该方法可以让线程发送信号通知等待中的线程继续运行。
当一个线程等待信号时,如果有其他线程调用Set方法发送了信号,则该线程可以继续运行。如果没有其他线程调用Set方法,则该线程会一直等待,直到另一个线程发送信号。
AutoResetEvent的使用步骤
AutoResetEvent的使用步骤一般如下:
- 创建AutoResetEvent对象。
- 在生产者线程中调用Set方法,发送信号。
- 在消费者线程中调用WaitOne方法,等待信号。
AutoResetEvent的示例
下面我们通过示例来具体分析AutoResetEvent的使用:
示例1:生产者消费者模型
我们可以通过AutoResetEvent来实现一个生产者-消费者模型。示例代码如下:
using System;
using System.Threading;
namespace AutoResetEventDemo
{
class Program
{
static AutoResetEvent autoResetEvent = new AutoResetEvent(false);
static void Main(string[] args)
{
Thread producerThread = new Thread(Producer);
Thread consumerThread = new Thread(Consumer);
producerThread.Start();
consumerThread.Start();
Console.ReadKey();
}
static void Producer()
{
for (int i = 0; i < 10; i++)
{
Console.WriteLine($"Producer: producing item {i}");
autoResetEvent.Set();
}
}
static void Consumer()
{
for (int i = 0; i < 10; i++)
{
autoResetEvent.WaitOne();
Console.WriteLine($"Consumer: consuming item {i}");
}
}
}
}
在该示例中,我们创建了一个AutoResetEvent对象,然后在生产者线程中循环生产10个物品,每生产一个物品就调用Set方法发送信号;在消费者线程中循环消费10个物品,每个循环中调用WaitOne方法等待信号,并在等到信号后打印一条消息表示消费了一个物品。
示例2:自定义线程池
我们还可以使用AutoResetEvent来实现一个自定义线程池。示例代码如下:
using System;
using System.Collections.Generic;
using System.Threading;
namespace AutoResetEventDemo
{
class Program
{
static AutoResetEvent autoResetEvent = new AutoResetEvent(false);
static List<Action> actionList = new List<Action>();
static Queue<Thread> threadPool = new Queue<Thread>();
static void Main(string[] args)
{
for (int i = 0; i < 5; i++)
{
Thread thread = new Thread(ThreadProc);
thread.Start();
threadPool.Enqueue(thread);
}
AddTask(() => Console.WriteLine("Task 1"));
AddTask(() => Console.WriteLine("Task 2"));
AddTask(() => Console.WriteLine("Task 3"));
AddTask(() => Console.WriteLine("Task 4"));
AddTask(() => Console.WriteLine("Task 5"));
Console.ReadKey();
}
static void AddTask(Action action)
{
actionList.Add(action);
autoResetEvent.Set();
}
static void ThreadProc()
{
while (true)
{
autoResetEvent.WaitOne();
Action action = null;
lock (actionList)
{
if (actionList.Count > 0)
{
action = actionList[0];
actionList.RemoveAt(0);
}
}
if (action != null)
{
action.Invoke();
}
else
{
lock (threadPool)
{
threadPool.Enqueue(Thread.CurrentThread);
}
break;
}
}
}
}
}
在该示例中,我们创建了一个自定义线程池,该线程池由5个线程构成,每当添加一个任务时就调用Set方法发送信号通知线程池中的线程去执行任务。在线程池中,每个线程都会使用WaitOne方法等待信号,收到信号后从任务列表中取出一个任务去执行;如果任务列表为空,就释放线程资源,将自身从线程池中移除。这样我们就实现了一个非常简单的自定义线程池。
以上示例只是AutoResetEvent的基本用法,AutoResetEvent还有其他一些属性和方法,可以根据自己的需要进行选择使用,希望本文对您有所帮助。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C#中AutoResetEvent控制线程用法小结 - Python技术站