好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

关于ThreadPool.RegisterWaitForSingleObject和WaitHandl

关于ThreadPool.RegisterWaitForSingleObject和WaitHandle的应用介绍

 最近在学习线程相关的内容,所以把学习过程中的心得记录下来,相信大家常用

            ThreadPool.QueueUserWorkItem()或者Thread thd=new Thread(new ThreadStart(test)))但是应该很少人知道用ThreadPool.RegisterWaitForSingleObject(高手除外啦),我也是最近才知道。让我来给各位看官解释一下它的用法吧,首先我们看一下它的原型:

Code
public   static  RegisteredWaitHandle RegisterWaitForSingleObject(
    WaitHandle waitObject,
    WaitOrTimerCallback callBack,
    Object state,
     int  millisecondsTimeOutInterval,
     bool  executeOnlyOnce
)

它的参数说明如下:

Parameters waitObject Type: System.Threading . . :: . WaitHandle

The WaitHandle to register. Use a WaitHandle other than Mutex .

callBack Type: System.Threading . . :: . WaitOrTimerCallback

The WaitOrTimerCallback delegate to call when the waitObject parameter is signaled.

state Type: System . . :: . Object

The object that is passed to the delegate.

millisecondsTimeOutInterval Type: System . . :: . Int32

The time-out in milliseconds. If the millisecondsTimeOutInterval parameter is 0 (zero), the function tests the object's state and returns immediately. If millisecondsTimeOutInterval is -1, the function's time-out interval never elapses.

executeOnlyOnce Type: System . . :: . Boolean

true to indicate that the thread will no longer wait on the waitObject parameter after the delegate has been called; false to indicate that the timer is reset every time the wait operation completes until the wait is unregistered.

Return Value

Type: System.Threading . . :: . RegisteredWaitHandle

The RegisteredWaitHandle that encapsulates the native handle.

相信看了这些之后大家还是一头雾水,这个方法的做用是向线程池添加一个可以定时执行的方法,第四个参数 millisecondsTimeOutInterval 就是用来设置间隔执行的时间,但是这里第五个参数 executeOnlyOnce 会对第四个参数起作用,当它为true时,表示任务仅会执行一次,就是说它不会,像Timer一样,每隔一定时间执行一次,这个功能的话用Timer控件也可以实现

该方法还在此基础上提供了基于信号量来触发执行任务。

信号量也叫开关量,故名思议,它只有两种状态,不是true就是false,

WaitHandle就是这类开关量的基础类,继承它的类有Mutex,ManualResetEvent,AutoResetEvent,一般我们使用后两个

写法:

Code
         static  ManualResetEvent wait2 = new  ManualResetEvent( false );
         static  AutoResetEvent wait = new  AutoResetEvent( false );

我们可以在将其实例化时指定开关量的初始值。(true为有信号,false为没信号)

ManualResetEvent和AutoResetEvent的区别在于:

前者调用Set方法后将自动将开关量值将一直保持为true,后者调用Set方法将变为true随后立即变为false,可以将它理解为一个脉冲。

我们来看几个例子

例子一:实现一个普通的定时器

Code
using  System;
using  System.Collections.Generic;
using  System.Linq;
using  System.Text;
using  System.Threading;

namespace  test
{
     class  Class14
    {
         static  AutoResetEvent wait = new  AutoResetEvent( false );
         static   void  Main( string [] args)
        {
             object  state = new   object ();
            ThreadPool.RegisterWaitForSingleObject(wait,  new  WaitOrTimerCallback(test11), state, 5000 ,  false );
            Console.ReadKey();
        }

         private   static   void  test11( object  state,  bool  timedOut)
        {
                Console.WriteLine( " aaa " );
        }
    }
}

  例子二,使用开关量提前执行下一次任务执行的时间为立即执行(有点绕,就是说原先间隔10s执行下一次任务,但是使用了开关量的set方法,立即执行下一次的任务,执行的时间提前了,下一次执行的时间又重新开始算

在这里请注意一个细节,下面的代码中当我们向线程池中注册任务的语句即            ThreadPool.RegisterWaitForSingleObject(wait, new WaitOrTimerCallback(test11), state,5000, false);
它是间隔5秒执行,当刚加入线程池后它是需要过了5秒后才会第一次执行回调函数的,也就是说不是一加入第0秒就会执行一次回调函数的。这里使用了一个wait.Set()方法使得立即执行了回调函数而不需要等待5秒钟,所以输出结果的第一个“aaa”是由wait.Set()操作引起的。

如果我们不使用wait.Set(),而是将AutoResetEvent wait=new AutoResetEvent(true)的初始值改为true也会在第0秒输出“aaa”

Code
using  System;
using  System.Collections.Generic;
using  System.Linq;
using  System.Text;
using  System.Threading;

namespace  test
{
     class  Class14
    {
         static  ManualResetEvent wait2 = new  ManualResetEvent( false );
         static  AutoResetEvent wait = new  AutoResetEvent( false );
         static   void  Main( string [] args)
        {
             object  state = new   object ();
            ThreadPool.RegisterWaitForSingleObject(wait,  new  WaitOrTimerCallback(test11), state, 5000 ,  false );
            wait.Set();
            Console.ReadKey();
        }

         private   static   void  test11( object  state,  bool  timedOut)
        {
                Console.WriteLine( " aaa " );
        }
    }
}

 第三个例子:使用ManualResetEvent,这个例子有点意思,它会不停的输出"aaa",为什么?

Code
using  System;
using  System.Collections.Generic;
using  System.Linq;
using  System.Text;
using  System.Threading;

namespace  test
{
     class  Class14
    {
         static  ManualResetEvent wait = new  ManualResetEvent( true );
         static   void  Main( string [] args)
        {
             object  state = new   object ();
            ThreadPool.RegisterWaitForSingleObject(wait,  new  WaitOrTimerCallback(test11), state, 5000 ,  false );

            Console.ReadKey();
        }

         private   static   void  test11( object  state,  bool  timedOut)
        {
                Console.WriteLine( " aaa " );
        }
    }
}

因为ManualResetEvent会一值保持开关量为true,所以会一直触发执行回调函数,

查看更多关于关于ThreadPool.RegisterWaitForSingleObject和WaitHandl的详细内容...

  阅读:37次