基元线程同步构造之 在一个内核构造可用时调用一个方法

  让一个线程不确定的等待一个内核对象进入可用状态,这对线程的内存资源来说是一种浪费。因此,线程池提供了一种方式,在一个内核对象变得可用的时候调用一个方法。这是通过System.Threading.ThreadPool类的静态RegisterWaitForSingleObject方法来实现的。该方法有几个重载的版本,但这些版本全都是很相似。以下是一个较常用的重载版本的原型:

  

public static RegisteredWaitHandle RegisterWaitForSingleObject(
   WaitHandle waitObject,
   WaitOrTimerCallback callback,
   Object state,
   Int32 millsecondsTimeoutInterval,
   Boolean executeOnlyOnce
);

参数说明:

  waitObject:标识了你希望线程池等待的内核对象,由于这个参数的类型是抽象基类WaitHandle,所以可以指定从这个基类派生的任何类。具体的说,可以传递          对一个Semaphore、Mutex、AutoResetEvent或者ManualResetEvent对象的引用。

  callback:标识了希望线程池线程调用的方法,这个回调方法必须匹配System.Threading.WaitOrTimerCallback委托:

          public delegate void WaitOrTimerCallback(Object state,Boolean timedOut)

  state:允许指定一些状态数据,线程池线程调用回调方法时,会将这个状态传给回调方法;如果没有特殊的状态数据需要传递,就传递null.

  millsecondsTimeoutInterval:指定了线程池在等待内核对象收到信号时的超时时间。一般传递 Timeout.Infinite(-1),将超时时间设为“无限长”。通俗点就是每                间隔多少时间执行一次 callback方法。

  executeOnlyOnce:为true时,线程池线程只执行回调方法一次,为false时,那么内核对象每次收到信号,线程此线程都会执行回调方法。

调用回调方法是,会向它传递状态数据和一个名为timedOut的Boolean值(通俗的说也就是在规定的时间millsecondsTimeoutInterval内,内核对象是否收到了信号),如果timedOut为false,方法知道他之所以被调用,是因为内核对象收到了信号。

     如果timedOut为true,方法知道它之所以被调用,是因为内核对象在指定的时间内没收到信号。

   注意:RegisterWaitForSingleObject方法返回的是对一个RegisteredWaitHandle对象的引用。这个对象标识了线程池线程正在它上面等待的内核对象。如果处于任何原因,你的应用程序向告诉线程池停止监视已登记的等待句柄,应用程序可以调用RegisteredWaitHandle的Unregister方法: 

public Boolean Unregister(WaitHandle waitObject);

  参数说明: waitObject参数指出,针对已登记等待句柄的、队列中的所有工作项都执行好之后,你想如何收到通知。

    如果不想接收通知,应该为这个参数传递null.

    如果传递的是对一个WaitHandle派生对象的有效引用,那么针对已登记的等待句柄的所有待决的工作项都执行完毕后,线程池线程就会向对象发出信号。

  以下代码演示了如果在一个AutoResetEvent对象收到信号之后,让一个线程池线程调用一个方法:

  

 1 // This example shows how a Mutex is used to synchronize access
 2 // to a protected resource. Unlike Monitor, Mutex can be used with
 3 // WaitHandle.WaitAll and WaitAny, and can be passed across
 4 // AppDomain boundaries.
 5 
 6 using System;
 7 using System.Threading;
 8 
 9 internal static class RegisteredWaitHandleDemo
10 {
11     public static void Main()
12     {
13         // Construct an AutoResetEvent (initially false)
14         AutoResetEvent are = new AutoResetEvent(false);
15 
16         // Tell the thread pool to wait on the AutoResetEvent告诉线程池在AutoResetEvent上等待
17         RegisteredWaitHandle rwh = ThreadPool.RegisterWaitForSingleObject(
18            are,             // Wait on this AutoResetEvent 在这个AutoResetEvent上等待
19            EventOperation,  // When available, call the EventOperation method 如果可用,就调用EventOperation方法
20            null,            // Pass null to EventOperation 向EventOperation传递null
21            5000,            // Wait 5 seconds for the event to become true 等5秒事件变成true,就执行 EventOperation回调方法,
                   // 也就是每间隔5秒执行一次EventOperation
22 false); // Call EventOperation everytime the event is true 每次事件为true时,都调用 EventOperation 23 24 // Start our loop 25 Char operation = (Char)0; 26 while (operation != 'Q') 27 { 28 Console.WriteLine("S=Signal, Q=Quit?"); 29 operation = Char.ToUpper(Console.ReadKey(true).KeyChar); 30 if (operation == 'S') are.Set(); // User want to set the event 31 } 32 33 // Tell the thread pool to stop waiting on the event,此处传递的是NULL,就不会向任何对象发送信号 34 rwh.Unregister(null); 35 } 36 37 // This method is called whenever the event is true or 38 // when 5 seconds have elapsed since the last callback/timeout 39 private static void EventOperation(Object state, Boolean timedOut) 40 { 41 Console.WriteLine(timedOut ? "Timeout" : "Event became true"); 42 } 43 }

以下的示例代码中 增加了取消登记时候发送信号的功能:

  

 1 // This example shows how a Mutex is used to synchronize access
 2 // to a protected resource. Unlike Monitor, Mutex can be used with
 3 // WaitHandle.WaitAll and WaitAny, and can be passed across
 4 // AppDomain boundaries.
 5 
 6 using System;
 7 using System.Threading;
 8 
 9 internal static class RegisteredWaitHandleDemo
10 {
11     public static void Main()
12     {
13         // Construct an AutoResetEvent (initially false)
14         AutoResetEvent are = new AutoResetEvent(false);
15 
16         AutoResetEvent arereult = new AutoResetEvent(false);
17 
18         System.Threading.Thread thr = new Thread(new ParameterizedThreadStart(TestUnregistered));
19         thr.Start(arereult);
20 
21         // Tell the thread pool to wait on the AutoResetEvent
22         RegisteredWaitHandle rwh = ThreadPool.RegisterWaitForSingleObject(
23            are,             // Wait on this AutoResetEvent
24            EventOperation,  // When available, call the EventOperation method
25            null,            // Pass null to EventOperation
26            5000,            // Wait 5 seconds for the event to become true
27            false);          // Call EventOperation everytime the event is true
28 
29         // Start our loop
30         Char operation = (Char)0;
31         while (operation != 'Q')
32         {
33             Console.WriteLine("S=Signal, Q=Quit?");
34             operation = Char.ToUpper(Console.ReadKey(true).KeyChar);
35             if (operation == 'S') are.Set(); // User want to set the event
36         }
37 
38         // Tell the thread pool to stop waiting on the event 取消注册后,向arereult发送信号,TestUnregistered就会解除阻塞
39         rwh.Unregister(arereult);
40 
41         Console.ReadLine();
42     }
43 
44     // This method is called whenever the event is true or
45     // when 5 seconds have elapsed since the last callback/timeout
46     private static void EventOperation(Object state, Boolean timedOut)
47     {
48         Console.WriteLine(timedOut ? "Timeout" : "Event became true");
49     }
50 
51     private static void TestUnregistered(object waithandle)
52     {
53         ((AutoResetEvent)waithandle).WaitOne();
54 
55         Console.WriteLine(" Test is TestUnregistered ");
56     }
57 
58 }

  

 以上的理解来源于 CLR 书中的理解。。。。。欢迎各位大侠们拍砖指正错误之处。。。。。。。。。。

原文地址:https://www.cnblogs.com/huaan011/p/3580406.html