标签:signal oev read 简介 hide ndt 标示 时间 ons
一、简介
我们使用类(.net Framework中的类,如 AutoResetEvent, Semaphore类等)的方法来实现线程同步的时候,其实内部是调用操作系统的内核对象来实现的线程同步。
System.Threading命名空间中提供了一个WaitHandle 的抽象基类,此类就是包装了一个Windows内核对象的句柄(句柄可以理解为标示了对象实例的一个数字),在.net Framework中提供了从WaitHandle类中派生的类。继承关系如下所示:
WaitHandle
EventWaitHandle
AutoResetEvent
ManualResetEvent
Semaphore
Mutex
当我们在使用 AutoResetEvent,ManualResetEvent,Semaphore,Mutex这些类的时候,用构造函数来实例化这些类的对象时,其内部都调用了Win32 CreateEvent或CreateEvent函数,或CreateSemaphore或者CreateMutex函数,这些函数调用返回的句柄值都保存在WaitHandle基类定义的SafeWaitHandle字段中。
二、AutoResetEvent (自动重置事件)
AutoResetEvent 在获得信号后,会自动将事件设置为无信号状态。
例1:事件初始化为无信号状态,主线程等待一段时间将事件设置为有信号状态
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading; 6 using System.Threading.Tasks; 7 8 namespace ThreadEvent 9 { 10 class Program 11 { 12 public static AutoResetEvent autoEvent = new AutoResetEvent(false); 13 static void Main(string[] args) 14 { 15 Task task = new Task(ThreadFunc); 16 task.Start(); 17 Console.WriteLine($"{DateTime.Now} Printed in main"); 18 Thread.Sleep(5000); 19 Console.WriteLine($"{DateTime.Now} Set signal in main"); 20 autoEvent.Set(); 21 Console.Read(); 22 } 23 private static void ThreadFunc() 24 { 25 PrintThreadInfo($"Printed in thread func"); 26 } 27 private static void PrintThreadInfo(string info) 28 { 29 if (autoEvent.WaitOne()) 30 { 31 //autoEvent.WaitOne(); 32 Console.WriteLine($"{DateTime.Now} {info}"); 33 Console.WriteLine($"{DateTime.Now} ThreadId:{Thread.CurrentThread.ManagedThreadId}\nIsBackgroundThread:{Thread.CurrentThread.IsBackground}\nIsThreadPoolThread:{Thread.CurrentThread.IsThreadPoolThread}"); 34 } 35 36 } 37 } 38 }
运行结果如下:
例2:事件初始化为无信号状态,主线程等待一段时间将事件设置为有信号状态,子线程连续两次Wait,观察第二次Wait的结果
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading; 6 using System.Threading.Tasks; 7 8 namespace ThreadEvent 9 { 10 class Program 11 { 12 public static AutoResetEvent autoEvent = new AutoResetEvent(false); 13 static void Main(string[] args) 14 { 15 Task task = new Task(ThreadFunc); 16 task.Start(); 17 Console.WriteLine($"{DateTime.Now} Printed in main"); 18 Thread.Sleep(5000); 19 Console.WriteLine($"{DateTime.Now} Set signal in main"); 20 autoEvent.Set(); 21 Console.Read(); 22 } 23 private static void ThreadFunc() 24 { 25 PrintThreadInfo($"Printed in thread func"); 26 } 27 private static void PrintThreadInfo(string info) 28 { 29 if (autoEvent.WaitOne()) 30 { 31 if (autoEvent.WaitOne(4000)) 32 { 33 Console.WriteLine($"{DateTime.Now} {info}"); 34 Console.WriteLine($"{DateTime.Now} ThreadId:{Thread.CurrentThread.ManagedThreadId}\nIsBackgroundThread:{Thread.CurrentThread.IsBackground}\nIsThreadPoolThread:{Thread.CurrentThread.IsThreadPoolThread}"); 35 } 36 else 37 { 38 Console.ForegroundColor = ConsoleColor.Red; 39 Console.WriteLine($"{DateTime.Now} WaitOne timeout!"); 40 Console.ResetColor(); 41 } 42 } 43 44 } 45 } 46 }
运行结果如下:
三、ManualResetEvent(手动重置事件)
ManualResetEvent在获得信号后,会一直保持有信号状态,除非我们手动调用Reset来将事件设置为无信号状态。
例1:
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading; 6 using System.Threading.Tasks; 7 8 namespace ThreadEvent 9 { 10 class Program 11 { 12 public static ManualResetEvent autoEvent = new ManualResetEvent(false); 13 static void Main(string[] args) 14 { 15 Task task = new Task(ThreadFunc); 16 task.Start(); 17 Console.WriteLine($"{DateTime.Now} Printed in main"); 18 Thread.Sleep(5000); 19 Console.WriteLine($"{DateTime.Now} Set signal in main"); 20 autoEvent.Set(); 21 Console.Read(); 22 } 23 private static void ThreadFunc() 24 { 25 PrintThreadInfo($"Printed in thread func"); 26 } 27 private static void PrintThreadInfo(string info) 28 { 29 if (autoEvent.WaitOne()) 30 { 31 //autoEvent.Reset(); 32 if (autoEvent.WaitOne(4000)) 33 { 34 Console.WriteLine($"{DateTime.Now} {info}"); 35 Console.WriteLine($"{DateTime.Now} ThreadId:{Thread.CurrentThread.ManagedThreadId}\nIsBackgroundThread:{Thread.CurrentThread.IsBackground}\nIsThreadPoolThread:{Thread.CurrentThread.IsThreadPoolThread}"); 36 } 37 else 38 { 39 Console.ForegroundColor = ConsoleColor.Red; 40 Console.WriteLine($"{DateTime.Now} WaitOne timeout!"); 41 Console.ResetColor(); 42 } 43 } 44 45 } 46 } 47 }
运行结果如下:
标签:signal oev read 简介 hide ndt 标示 时间 ons
原文地址:https://www.cnblogs.com/3xiaolonglong/p/9650908.html