上图的所有多线程案例大全完整版本项目源代码下载---->点击下载
C#多线程阻塞:选择AutoResetEvent
与ManualResetEvent
的业务场景
在C#多线程编程中,AutoResetEvent
和ManualResetEvent
是两种常用的同步原语,用于控制线程间的协调和通信。它们各自适用于不同的业务场景,选择哪一种取决于具体的并发需求。
使用AutoResetEvent
的业务场景:
-
单个资源的访问控制:当多个线程需要按顺序访问一个共享资源时,
AutoResetEvent
可以确保每次只有一个线程能够进行访问。 -
生产者-消费者模式:在这种模式下,生产者生产数据后,
AutoResetEvent
用来通知消费者进行消费,一旦一个消费者开始消费,事件自动重置,为下一轮生产和消费做准备。 -
异步操作的同步:在执行异步I/O操作,如文件读写、网络通信时,
AutoResetEvent
可以用来通知主线程异步操作已完成。 -
任务完成通知:当一个后台线程完成其任务后,可以使用
AutoResetEvent
来通知其他线程或主线程进行后续操作。 -
单次信号响应:在某些情况下,线程需要对某个事件做出单次响应,如监控线程检测到异常情况后通知处理线程进行处理。
使用ManualResetEvent
的业务场景:
-
多条件同步:当需要等待多个事件或条件都满足时,
ManualResetEvent
可以保持信号状态,直到所有条件都满足后,才进行下一步操作。 -
复合资源访问:如果存在多个资源,且需要所有资源都准备好才能进行操作,
ManualResetEvent
可以用于这种多资源的同步。 -
批量数据处理:在处理批量数据时,可能需要等待所有数据都处理完毕后,再进行汇总或后续处理,
ManualResetEvent
可以在此场景下使用。 -
线程间的复杂协调:在涉及多个线程且线程间需要进行复杂协调的场景,
ManualResetEvent
提供了更灵活的控制,可以手动管理事件的信号状态。 -
一次性初始化:在程序启动时,可能需要等待某些资源或服务初始化完成后才能继续执行,
ManualResetEvent
可以在此场景下确保程序在初始化完成后才开始运行。 -
等待所有子任务完成:当主线程需要等待所有子任务完成后才能结束时,可以使用
ManualResetEvent
来同步所有子任务的完成状态。
结论
AutoResetEvent
和ManualResetEvent
各有其适用场景。AutoResetEvent
适合于简单的、单次的线程间通信,而ManualResetEvent
则适用于需要手动控制信号状态,或者需要等待多个条件的场景。在实际应用中,选择哪种事件取决于具体的业务逻辑和并发控制需求。正确地使用这些同步原语对于提高程序的稳定性和性能至关重要。
static AutoResetEvent autoEvent = new AutoResetEvent(false); // 初始化
private void button26_Click(object sender, EventArgs e)
{
//Thread producer = new Thread(Produce);
//Thread consumer = new Thread(Consume);
//producer.Start();
//consumer.Start();
Task.Run(() =>
{
Produce();
});
Task.Run(() =>
{
Consume();
});
}
private void Produce()
{
for (int i = 0; i < 5; i++)
{
Console.WriteLine("生产者生产了产品: " + (i+1));
// 模拟生产产品所需的时间
Thread.Sleep(1000);
// 产品生产完毕,触发事件通知消费者
autoEvent.Set();
}
}
private void Consume()
{
for (int i = 0; i < 5; i++)
{
// 等待生产者生产产品
autoEvent.WaitOne();
// 模拟消费产品所需的时间
Console.WriteLine("消费者消费了产品: " + (i + 1));
//Thread.Sleep(100);
}
}