C# 使用ManualResetEvent 进行线程同步

简介: 上一篇我们介绍了AutoResetEvent,这一篇我们来看下ManualResetEvent ,顾名思义ManualResetEvent  为手动重置事件。 AutoResetEvent和ManualResetEvent这两个类经常用到, 他们的用法很类似,但也有区别。

上一篇我们介绍了AutoResetEvent,这一篇我们来看下ManualResetEvent ,顾名思义ManualResetEvent  为手动重置事件。

AutoResetEvent和ManualResetEvent这两个类经常用到, 他们的用法很类似,但也有区别。

Set方法将信号置为发送状态,Reset方法将信号置为不发送状态,WaitOne等待信号的发送。可以通过构造函数的参数值来决定其初始状态,若为true则非阻塞状态,为false为阻塞状态。如果某个线程调用WaitOne方法,则当信号处于发送状态时,该线程会得到信号, 继续向下执行。

 

 

 

 static ManualResetEvent a = new ManualResetEvent(false);

        public static void MainTest()
        {
            Thread[] ths = new Thread[4];
            for (int i = 0; i < 4; i++)
            {
                ths[i] = new Thread(increaseCount);
                ths[i].Start();
            }
            a.Set();
            // x.ReleaseMutex();
            System.Console.ReadKey();
        }

        static void increaseCount()
        {
            a.WaitOne();
            //a.Reset();
            Random ran = new Random();
            Thread.Sleep(ran.Next(100, 5000));
            int beginNum = SharedResource2.Count;
            System.Console.WriteLine("线程 {0} 读到的起始值为 {1}  ", Thread.CurrentThread.ManagedThreadId, beginNum);
            for (int i = 0; i < 10000; i++)
            {
                beginNum++;
            }

            SharedResource2.Count = beginNum;
            System.Console.WriteLine("线程 {0} 结束,SharedResource.Count={1}", Thread.CurrentThread.ManagedThreadId, SharedResource2.Count);
            a.Set();
        }

class SharedResource2
{
public static int Count = 0;
}

 

 

为什么会出现这个结果,这明显不是我们想要的,原因在于ManualResetEvent则可以唤醒多个线程(这区别于AutoResetEvent),因为当某个线程调用了ManualResetEvent.Set()方法后,其他调用WaitOne的线程获得信号得以继续执行,而ManualResetEvent不会自动将信号置为不发送。也就是说,除非手工调用了ManualResetEvent.Reset()方法,则ManualResetEvent将一直保持有信号状态,ManualResetEvent也就可以同时唤醒多个线程继续执行。

 static ManualResetEvent a = new ManualResetEvent(false);

        public static void MainTest()
        {
            Thread[] ths = new Thread[4];
            for (int i = 0; i < 4; i++)
            {
                ths[i] = new Thread(increaseCount);
                ths[i].Start();
            }
            a.Set();
            // x.ReleaseMutex();
            System.Console.ReadKey();
        }

        static void increaseCount()
        {
            a.WaitOne();
            a.Reset();
            Random ran = new Random();
            Thread.Sleep(ran.Next(100, 5000));
            int beginNum = SharedResource2.Count;
            System.Console.WriteLine("线程 {0} 读到的起始值为 {1}  ", Thread.CurrentThread.ManagedThreadId, beginNum);
            for (int i = 0; i < 10000; i++)
            {
                beginNum++;
            }

            SharedResource2.Count = beginNum;
            System.Console.WriteLine("线程 {0} 结束,SharedResource.Count={1}", Thread.CurrentThread.ManagedThreadId, SharedResource2.Count);
            a.Set();
        }

class SharedResource2
{
public static int Count = 0;
}

 

 

 

相关文章
|
8月前
|
SQL 开发框架 安全
C#编程与多线程处理
【4月更文挑战第21天】探索C#多线程处理,提升程序性能与响应性。了解C#中的Thread、Task类及Async/Await关键字,掌握线程同步与安全,实践并发计算、网络服务及UI优化。跟随未来发展趋势,利用C#打造高效应用。
217 3
|
8月前
|
安全 编译器 C#
C#学习相关系列之多线程---lock线程锁的用法
C#学习相关系列之多线程---lock线程锁的用法
|
8月前
|
并行计算 安全 Java
C# .NET面试系列四:多线程
<h2>多线程 #### 1. 根据线程安全的相关知识,分析以下代码,当调用 test 方法时 i > 10 时是否会引起死锁? 并简要说明理由。 ```c# public void test(int i) { lock(this) { if (i > 10) { i--; test(i); } } } ``` 在给定的代码中,不会发生死锁。死锁通常是由于两个或多个线程互相等待对方释放锁而无法继续执行的情况。在这个代码中,只有一个线程持有锁,且没有其他线程参与,因此不
428 3
|
8月前
|
Java 调度 C#
C#学习系列相关之多线程(一)----常用多线程方法总结
C#学习系列相关之多线程(一)----常用多线程方法总结
|
8月前
|
C#
C#学习相关系列之多线程---ConfigureAwait的用法
C#学习相关系列之多线程---ConfigureAwait的用法
146 0
|
8月前
|
C#
C#学习相关系列之多线程---TaskCompletionSource用法(八)
C#学习相关系列之多线程---TaskCompletionSource用法(八)
238 0
|
8月前
|
Java C#
C#学习系列相关之多线程(五)----线程池ThreadPool用法
C#学习系列相关之多线程(五)----线程池ThreadPool用法
198 0
|
5月前
|
数据采集 XML JavaScript
C# 中 ScrapySharp 的多线程下载策略
C# 中 ScrapySharp 的多线程下载策略
|
4月前
|
安全 数据库连接 API
C#一分钟浅谈:多线程编程入门
在现代软件开发中,多线程编程对于提升程序响应性和执行效率至关重要。本文从基础概念入手,详细探讨了C#中的多线程技术,包括线程创建、管理及常见问题的解决策略,如线程安全、死锁和资源泄露等,并通过具体示例帮助读者理解和应用这些技巧,适合初学者快速掌握C#多线程编程。
89 0