首页 技术 正文
技术 2022年11月20日
0 收藏 774 点赞 4,895 浏览 3450 个字

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

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

ThreadPool基础之RegisterWaitForSingleObjectThreadPool基础之RegisterWaitForSingleObjectCode
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,可以将它理解为一个脉冲。

我们来看几个例子

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

ThreadPool基础之RegisterWaitForSingleObjectThreadPool基础之RegisterWaitForSingleObjectCode
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”

ThreadPool基础之RegisterWaitForSingleObjectThreadPool基础之RegisterWaitForSingleObjectCode
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",为什么?

ThreadPool基础之RegisterWaitForSingleObjectThreadPool基础之RegisterWaitForSingleObjectCode
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,所以会一直触发执行回调函数。

相关推荐
python开发_常用的python模块及安装方法
adodb:我们领导推荐的数据库连接组件bsddb3:BerkeleyDB的连接组件Cheetah-1.0:我比较喜欢这个版本的cheeta…
日期:2022-11-24 点赞:878 阅读:9,104
Educational Codeforces Round 11 C. Hard Process 二分
C. Hard Process题目连接:http://www.codeforces.com/contest/660/problem/CDes…
日期:2022-11-24 点赞:807 阅读:5,581
下载Ubuntn 17.04 内核源代码
zengkefu@server1:/usr/src$ uname -aLinux server1 4.10.0-19-generic #21…
日期:2022-11-24 点赞:569 阅读:6,428
可用Active Desktop Calendar V7.86 注册码序列号
可用Active Desktop Calendar V7.86 注册码序列号Name: www.greendown.cn Code: &nb…
日期:2022-11-24 点赞:733 阅读:6,200
Android调用系统相机、自定义相机、处理大图片
Android调用系统相机和自定义相机实例本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显…
日期:2022-11-24 点赞:512 阅读:7,835
Struts的使用
一、Struts2的获取  Struts的官方网站为:http://struts.apache.org/  下载完Struts2的jar包,…
日期:2022-11-24 点赞:671 阅读:4,918