WPF-09 ManualResetEventSlim信号量

业务场景如下:WPF应用程序后台有个定时任务在接收PLC硬件数据(该线程接收完数据之后, 会重新启动一个新线程继续接收.....),当应用程序关闭时, 我们得确保接收PLC硬件数据的线程完成之后,再关闭应用程序,否则会造成数据丢失。
上面的业务场景是前一段时间一个朋友向我请教WPF的问题,项目中有一个ManualResetEventSlim类 ,不知道这个类是干什么的。由于本人从事WPF的工作将近10年,在项目中用到过不少与线程相关联的类,所以在这做个简单介绍,做过C/S架构的朋友对多线程接触会更多,那么线程与线程之间是如果通信呢?就是通过ManualResetEventSlim类来完成,其实这个类和ManualResetEvent功能上是一样。ManualResetEventSlim 更轻量级一些。我们解释一下这个类具体用法:.
static void MRES_SetWaitReset(){     System.Threading.ManualResetEventSlim mres1 = new System.Threading.ManualResetEventSlim(false); // initialize as unsignaled     System.Threading.ManualResetEventSlim mres2 = new System.Threading.ManualResetEventSlim(false); // initialize as unsignaled     System.Threading.ManualResetEventSlim mres3 = new System.Threading.ManualResetEventSlim(true);  // initialize as signaled     // Start an asynchronous Task that manipulates mres3 and mres2     var observer = Task.Factory.StartNew(() =>     {         mres1.Wait();         Console.WriteLine("observer sees signaled mres1!");         Console.WriteLine("observer resetting mres3...");         mres3.Reset(); // should switch to unsignaled         Console.WriteLine("observer signalling mres2");         mres2.Set();       });
      Console.WriteLine("main thread: mres3.IsSet = {0} (should be true)", mres3.IsSet);      Console.WriteLine("main thread signalling mres1");      mres1.Set(); // This will "kick off" the observer Task      mres2.Wait(); // This won't return until observer Task has finished resetting mres3      Console.WriteLine("main thread sees signaled mres2!");      Console.WriteLine("main thread: mres3.IsSet = {0} (should be false)", mres3.IsSet);      // It's good form to Dispose() a ManualResetEventSlim when you're done with it      observer.Wait(); // make sure that this has fully completed      mres1.Dispose();      mres2.Dispose();      mres3.Dispose();}

当前方法有两个线程:主线程和oberver子线程。应用程序运行时,这两个线程同时执行,oberver子线程调用mres1.Wait(),所以使oberver子线程处于等待。主线程继续运行,当调用mres1.Set()主线程会给oberver子线程发个信号,主线程对oberver子线程说:"ok,oberver子线程你可以继续运行了",这时oberver线程mres1.Wait()收到该信号后,不再等待,继续执行下面代码。主线程执行到 mres2.Wait();方法时,这时主线程会挂起,处于等待状态,这时oberver子线程继续执行,当oberver子线程运行到mres2.Set(); oberver子线程会给主线程发送一个信号,oberver子线程会对主线程说:"OK,主线程可以运行了",于是mres2.Wait()不再等待,会继续运行. OK, 这就是这个方法的大体执行流程.

总结:ManualResetEventSlim类
  • Wait()方法内部检测到IsSet属性的值,如果为false,线程会挂起。如果为IsSet为ture,线程不会挂起会继续执行。
  • Reset()会将IsSet设置成false。
  • Set() 会将这IsSet设置成true。 
备注:Wait()内部通过轮训来判断这个值.来决定时候处于等待状态。