ManualResetEvent
ManualResetEvent有三个重要的方法,分别为:waiteone(),set(),reset(),其含义如下:
1.WaitOne()即等待信号发出,即可往下运行。
2.set()发出信号,让线程方法继续往下运行,并允许其他线程(如有)一并往下运行。
3.reset()重新初始化(即:去掉票据)变为ManualResetEvent(false)形式。
官方示例如下:
internal class Program {private static ManualResetEvent mre = new ManualResetEvent(false);static void Main(){Console.WriteLine("\n初始化3个线程,并在遇到waitone时阻塞运行:\n");for (int i = 0; i <= 2; i++){Thread t = new Thread(ThreadProc);t.Name = "Thread_" + i;t.Start();}Thread.Sleep(500);Console.WriteLine("\n三个线程已经启动,请按回车键调用Set()方法来释放3个阻塞线程");Console.ReadLine();mre.Set();Thread.Sleep(500);Console.WriteLine("\n当这个ManualResetEvent活得信号,3个线程都会从WaitOne()方法内返回,并继续运行(如果有新线程被创建)不会被阻塞,可按回车键进行观察:\n");Console.ReadLine();for (int i = 3; i <= 4; i++){Thread t = new Thread(ThreadProc);t.Name = "Thread_" + i;t.Start();}Thread.Sleep(500);Console.WriteLine("\n按回车键调用 Reset()方法(设置为无信号状态),重新初始化一个线程运行,并在WaitOne()方法处停下来\n");Console.ReadLine();mre.Reset();// Start a thread that waits on the ManualResetEvent.Thread t5 = new Thread(ThreadProc);t5.Name = "Thread_5";t5.Start();Thread.Sleep(500);Console.WriteLine("\n按回车键调用 Set() 方法,然后结束演示.");Console.ReadLine();mre.Set();Console.ReadLine();}private static void ThreadProc(){string name = Thread.CurrentThread.Name;Console.WriteLine(name + " starts and calls mre.WaitOne()");mre.WaitOne();Console.WriteLine(name + " ends.");} }
运行结果:
ManualResetEventSlim:
ManualResetEventSlim是ManualResetEvent的简化版或者叫优化版,其主要原理为采用了自旋方式来提高性能,适用于短期内等待的情况,性能比后者要好很多。适用于一次写入,多次读取时候的线程同步场景。
官方示例代码:
internal class Program{static void Main(string[] args){MRES_SetWaitReset();Console.ReadKey();}static void MRES_SetWaitReset(){ManualResetEventSlim mres1 = new ManualResetEventSlim(false);ManualResetEventSlim mres2 = new ManualResetEventSlim(false);ManualResetEventSlim mres3 = new ManualResetEventSlim(true); var observer = Task.Factory.StartNew(() =>{mres1.Wait();Console.WriteLine("mres1!阻塞结束继续运行");Console.WriteLine("mres3即将被重置");mres3.Reset(); Console.WriteLine("mres2即将获取到票据");mres2.Set();});Console.WriteLine("主线程: mres3.IsSet = {0} (should be true)", mres3.IsSet);Console.WriteLine("主线程:mres1即将获取信号");mres1.Set();Console.WriteLine("主线程:mres2即将阻塞");mres2.Wait();Console.WriteLine("主线程:mres2已获取信号!");Console.WriteLine("主线程: mres3.IsSet = {0} (should be false)", mres3.IsSet);observer.Wait(); // make sure that this has fully completed mres1.Dispose();mres2.Dispose();mres3.Dispose();}}
运行结果: