• 关于ThreadPool.RegisterWaitForSingleObject和WaitHandle的应用介绍 【转】


    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,一般我们使用后两个

    写法:


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

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

    ManualResetEvent和AutoResetEvent的区别在于:

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

    我们来看几个例子

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

    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”

    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",为什么?

    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,所以会一直触发执行回调函数。

    转自:http://www.cnblogs.com/lexus/archive/2008/08/08/1263718.html

  • 相关阅读:
    leetcode-654-最大二叉树
    leetcode-46-全排列
    图片懒加载?
    HTTP常见的状态码?
    线程与进程的区别?
    网页从输入网址到渲染完成经历了哪些过程?
    网页前端性能优化的方式有哪些?
    常见的浏览器内核有哪些?
    汇编语言--cpu的工作原理(寄存器)--手稿
    对于 vue3.0 特性你有什么了解的吗?
  • 原文地址:https://www.cnblogs.com/bayonetxxx/p/1698954.html
Copyright © 2020-2023  润新知