ManualResetEvent&ManualResetEventSlim
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(); } }
运行结果: