原文发布时间为:2010-10-27 —— 来源于本人的百度文章 [由搬家工具导入]

首先我们看一下它的原型:

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

waitObject

要注册的 WaitHandle。使用 WaitHandle 而非 Mutex

callBack

waitObject 参数终止时调用的 WaitOrTimerCallback 委托。

state

传递给委托的对象。

timeout

TimeSpan 表示的超时时间。如果 timeout 为零,则函数测试对象的状态并立即返回。如果 timeout 为 -1,则函数的超时间隔永远不过期。

executeOnlyOnce

如果为 true,表示在调用了委托后,线程将不再在 waitObject 参数上等待;如果为 false,表示每次完成等待操作后都重置计时器,直到注销等待。

返回值

封装本机句柄的 RegisteredWaitHandle

相信看了这些之后大家还是一头雾水,这个方法的做用是向线程池添加一个可以定时执行的方法,第四个参数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,可以将它理解为一个脉冲。

我们来看几个例子

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

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的更多相关文章

  1. 线程池基础 ThreadPool基础

    原文发布时间为:2010-10-27 -- 来源于本人的百度文章 [由搬家工具导入] 池(Pool)是一个很常见的提高性能的方式。比如线程池连接池等,之所以有这些池是因为线程和数据库连接的创建和关闭是 ...

  2. 封装Socket.BeginReceive/EndReceive支持Timeout简介

    .NET中的Socket类提供了网络通信常用的方法,分别提供了同步和异步两个版本,其中异步的实现是基于APM异步模式实现,即BeginXXX/EndXXX的方式.异步方法由于其非阻塞的特性,在需考虑程 ...

  3. 用惯了Task,你应该也需要了解它的内部调度机制TaskScheduler

    平时我们在用多线程开发的时候少不了Task,确实task给我们带来了巨大的编程效率,在Task底层有一个TaskScheduler,它决定了task该如何执行,而在 .net framework中有两 ...

  4. 封装Socket.BeginReceive/EndReceive以支持Timeout

    Socket .NET中的Socket类提供了网络通信常用的方法,分别提供了同步和异步两个版本,其中异步的实现是基于APM异步模式实现,即BeginXXX/EndXXX的方式.异步方法由于其非阻塞的特 ...

  5. C#中的线程池使用(二)

    线程池是后台线程.每个线程都使用默认的堆栈大小,以默认的优先级运行,并处于多线程单元中.每个进程只有一个线程池对象. 下面说一下线程池中的异常,在线程池中未处理的异常将终止进程.以下为此规则的三种例外 ...

  6. C#TaskScheduler 任务调度器的原理

    什么是TaskScheduler? SynchronizationContext是对"调度程序(scheduler)"的通用抽象.个别框架会有自己的抽象调度程序,比如System. ...

  7. .net 线程基础 ThreadPool 线程池

    1. ThreadPool 线程池异步: //public static bool QueueUserWorkItem(WaitCallback callBack); //public static ...

  8. C#中的多线程 - 同步基础

    原文:http://www.albahari.com/threading/part2.aspx 文章来源:http://blog.gkarch.com/threading/part2.html 1同步 ...

  9. C#线程池基础

    池(Pool)是一个很常见的提高性能的方式.比如线程池连接池等,之所以有这些池是因 为线程和数据库连接的创建和关闭是一种比较昂贵的行为.对于这种昂贵的资源我们往往会考虑在一个池容器中放置一些资源,在用 ...

随机推荐

  1. Springboot 入门创建hello world1!

    1.首先使用工具是Eclipse,安装插件,点击“Help”-“Eclipse Marketplace...”, 一步步直接Ok,等待安装完成 2.创建Springboot项目 到此 就创建成功了 3 ...

  2. pycharm配置Git托管

    利用Pycharm和github管理代码转载https://www.cnblogs.com/feixuelove1009/p/5955332.html git教程--廖雪峰git教程  转载https ...

  3. Python学习笔记:math模块(数学),random模块(随机数)

    math模块 math模块用于数学意义上的一些计算,常用的方法有: math.pi:PI的值(3.141592653589793). math.floor(x):返回一个小于等于x的最大整数(浮点类型 ...

  4. 权限组件(15):rbac的使用文档和在业务中的应用

    这里用主机管理系统当做示例. 一.将rbac组件拷贝到项目中. 注意: rbac自己的静态文件.layout.html(被继承的模板).bootstrap.fontsize.公共的css.jquery ...

  5. 使用virtualbox安装的Ubuntu,窗口分辨率过小,使用增强工具完成和vmtools一样的功能。

    今天用VirtualBox成功装上Ubuntu10.04之后发现了一个问题:默认情况下 ubuntu 的分辨率最高只能设到800*600.但是对于自己的大显示器,在分辨率800*600的ubuntu窗 ...

  6. The Tower of Babylon UVA - 437 DAG上的动态规划

    题目:题目链接 思路:每个方块可以用任意多次,但因为底面限制,每个方块每个放置方式选一个就够了,以x y为底 z 为高,以x z为底 y 为高,以y z为底 x为高,因为数据量很小,完全可以把每一种当 ...

  7. python使用@property @x.setter @x.deleter

    @property可以将python定义的函数“当做”属性访问,从而提供更加友好访问方式,但是有时候setter/deleter也是需要的. 1>只有@property表示只读. 2>同时 ...

  8. 4 Template层-CSRF

    1.csrf 全称Cross Site Request Forgery,跨站请求伪造 某些恶意网站上包含链接.表单按钮或者JavaScript,它们会利用登录过的用户在浏览器中的认证信息试图在你的网站 ...

  9. 03015_JSTL技术

    1.JSTL概述 (1)JSP(JSP Standard Tap Library),JSP标准标签库,可以嵌入在jsp页面中使用标签的形式完成业务逻辑等功能.jstl出现的目的同el一样也是要替代js ...

  10. redis 之相关命令

    为什么缓存数据库更要首选redis?如何使用redis? 一.使用缓存数据库为什么首选用redis? 我们都知道,把一些热数据存到缓存中可以极大的提高速度,那么问题来了,是用Redis好还是Memca ...