在所有的内核对象中,事件内核对象是个最基本的对象。事件能够通知一个操作已经完成。

客户机和一个服务器,它们之间需要互相进行通信例子(vs2008 )

事件内核对象的组成

一个使用计数(与所有内核对象一样),

一个用于指明该事件是个自动重置的事件还是一个人工重置的事件的布尔值,

一个用于指明该事件处于已通知状态还是未通知状态的布尔值。

有两种不同类型的事件对象

一种是人工重置的事件,另一种是自动重置的事件。

当人工重置的事件得到通知时,等待该事件的所有线程均变为可调度线程。

当自动重置的事件得到通知时,等待该事件的线程中只有一个线程变为可调度线程。

当一个线程执行初始化操作,然后通知另一个线程执行剩余的操作时,事件使用得最多。事件初始化为未通知状态,然后,当该线程完成它的初始化操作后,它就将事件设置为已通知状态。这时,一直在等待该事件的另一个线程发现该事件已经得到通知,因此它就变成可调度线程。这第二个线程知道第一个线程已经完成了它的操作。

CreateEvent函数创建事件内核对象

HANDLE CreateEvent(

PSECURITY_ATTRIBUTES psa,

BOOL fManualReset,

BOOL fInitialState,

PCTSTR pszName

);

内核对象的操作技巧见前面相关章节,比如,如何设置它们的安全性,如何进行使用计数如何继承它们的句柄如何按名字共享对象等

fMannualReset参数是个布尔值,它能够告诉系统是创建一个人工重置的事件(TRUE)还是创建一个自动重置的事件(FALSE)。

fInitialState参数用于指明该事件是要初始化为已通知状态(TRUE)还是未通知状态(FALSE)。当系统创建事件对象后, createEvent就将与进程相关的句柄返回给事件对象。

其他进程中的线程可以获得对该对象的访问权,方法是使用在pszName参数中传递的相同值(见:命名对象),使用继承性使用DuplicateHandle函数等来调用CreateEvent,或者调用OpenEvent ,在pszName参数中设定一个与调用CreateEvent时设定的名字相匹配的名字:

HANDLE OpenEvent(

DWORD fdwAccess,

BOOL fInherit,

PCTSTR pszName

);

与所有情况中一样,当不再需要事件内核对象时,应该调用CloseHandle函数。

一旦事件已经创建,就可以直接控制它的状态

当调用SetEvent时,可以将事件改为已通知状态:

BOOL SetEvent(HANDLE hEvent);

当调用ResetEvent函数时,可以将该事件改为未通知状态:

BOOL ResetEvent(HANDLE hEvent);

事件成功等待的副作用

自动重置的事件:自动重置到未通知状态(所以通常没有必要为自动重置的事件调用ResetEvent函数)。所以他的名字才有自动两字。

人工重置的事件: Microsoft没有为人工重置的事件定义成功等待的副作用。所以它才叫人工。

简单例子,如何使用事件内核对象对线程进行同步

这个例子清楚地展示出使用人工重置事件与自动重置事件之间的差别。

// Create a global handle to a manual-reset, nonsignaled event.

HANDLE g_hEvent;

int WINAPI WinMain(...)

{

// Create the manual-reset, nonsignaled event.

g_hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);    //人工

// Spawn 3 new threads.

HANDLE hThread[3];

DWORD dwThreadID;

hThread[0] = _beginthreadex(NULL, 0, WordCount, NULL, 0, &dwThreadID);

hThread[1] = _beginthreadex(NULL, 0, SpellCheck, NULL, 0, &dwThreadID);

hThread[2] = _beginthreadex(NULL, 0, GrammarCheck, NULL, 0, &dwThreadID);

OpenFileAndReadContentsIntoMemory(...);

//Allow all 3 threads to access the memory.

SetEvent(g_hEvent);              // 将事件设置已通知状态

...

}

DWORD WINAPI WordCount(PVOID pvParam)

{

//Wait until the file's data is in memory.

WaitForSingleObject(g_hEvent, INFINITE);

//Access the memory block.

...

return(0);

}

DWORD WINAPI SpellCheck(PVOID pvParam)

{

//Wait until the file's data is in memory.

WaitForSingleObject(g_hEvent, INFINITE);

//Access the memory block.

...

return(0);

}

DWORD WINAPI GrammarCheck(PVOID pvParam)

{

//Wait until the file's data is in memory.

WaitForSingleObject(g_hEvent, INFINITE);

//Access the memory block.

...

return(0);

}

当这个进程启动时,它创建一个人工重置的未通知状态的事件,并且将句柄保存在一个全局变量中。这使得该进程中的其他线程能够非常容易地访问同一个事件对象。现在3个线程已经产生。这些线程要等待文件的内容读入内存,然后每个线程都要访问它的数据。一个线程进行单词计数,另一个线程运行拼写检查器,第三个线程运行语法检查器。这3个线程函数的代码的开始部分都相同,每个函数都调用WaitForSingleObject,这将使线程暂停运行,直到文件的内容由主线程读入内存为止。

一旦主线程将数据准备好,它就调用SetEvent,给事件发出通知信号。这时,系统就使所有这3个辅助线程进入可调度状态,它们都获得了CPU时间,并且可以访问内存块。注意,这3个线程都以只读方式访问内存。这就是所有3个线程能够同时运行的唯一原因。还要注意,如果计算机上配有多个CPU,那么所有3个线程都能够真正地同时运行,从而可以在很短的时间内完成大量的操作。

如果这里使用自动重置的事件而不是人工重置的事件,那么应用程序的行为特性就有很大的差别。当主线程调用SetEvent之后,系统只允许一个辅助线程变成可调度状态。同样,也无法保证系统将使哪个线程变为可调度状态。其余两个辅助线程将继续等待。

已经变为可调度状态的线程拥有对内存块的独占访问权。让我们重新编写线程的函数,使得每个函数在返回前调用SetEvent函数(就像WinMain函数所做的那样)。这些线程函数现在变成下面的形式:

DWORD WINAPI WordCount(PVOID pvParam)

{

//Wait until the file's data is in memory.

WaitForSingleObject(g_hEvent, INFINITE);

//Access the memory block.

...

SetEvent(g_hEvent);

return(0);

}

DWORD WINAPI SpellCheck(PVOID pvParam)

{

//Wait until the file's data is in memory.

WaitForSingleObject(g_hEvent, INFINITE);

//Access the memory block.

...

SetEvent(g_hEvent);

return(0);

}

DWORD WINAPI GrammarCheck(PVOID pvParam)

{

//Wait until the file's data is in memory.

WaitForSingleObject(g_hEvent, INFINITE);

//Access the memory block.

...

SetEvent(g_hEvent);

return(0);

}

当线程完成它对数据的专门传递时,它就调用SetEvent函数,该函数允许系统使得两个正在等待的线程中的一个成为可调度线程。同样,我们不知道系统将选择哪个线程作为可调度线程,但是该线程将进行它自己的对内存块的专门传递。当该线程完成操作时,它也将调用SetEvent函数,使第三个即最后一个线程进行它自己的对内存块的传递。注意,当使用自动重置事件时,如果每个辅助线程均以读/写方式访问内存块,那么就不会产生任何问题,这些线程将不再被要求将数据视为只读数据。

BOOL PulseEvent(HANDLE hEvent);

PulseEvent函数使得事件变为已通知状态,然后立即又变为未通知状态,这就像在调用SetEvent后又立即调用ResetEvent函数一样。如果在人工重置的事件上调用PulseEvent函数,那么在发出该事件时,等待该事件的任何一个线程或所有线程将变为可调度线程。如果在自动重置事件上调用PulseEvent函数,那么只有一个等待该事件的线程变为可调度线程。如果在发出事件时没有任何线程在等待该事件,那么将不起任何作用。

PulseEvent函数并不非常有用(可以先不管它)。

原文地址:http://www.cnblogs.com/fangyukuan/archive/2010/09/04/1817750.html

(转)内核线程对象--Event事件对象的更多相关文章

  1. Python多线程-Event(事件对象)

    Event 事件对象管理一个内部标志,通过set()方法将其设置为True,并使用clear()方法将其设置为False.wait()方法阻塞,直到标志为True.该标志初始为False. 方法: i ...

  2. trigger()的event事件对象之坑

    问题引入,先贴一段有问题的代码,如果你对 trigger()  这个函数了解不透彻,还真看不出这段代码错在哪.完成的功能是样式转换器,想让页面在加载后自行触发点击事件隐藏三个按钮,但是效果如图并没有隐 ...

  3. 简单总结焦点事件、Event事件对象、冒泡事件

    每学习一些新的东西,要学会复习,总结和记录. 今天来简单总结一下学到的几个事件:焦点事件.Event事件对象.冒泡事件 其实这几个事件应该往深的说是挺难的,但今天主要是以一个小菜的角度去尝试理解一些基 ...

  4. 第53天:鼠标事件、event事件对象

    -->鼠标事件-->event事件对象-->默认事件-->键盘事件(keyCode)-->拖拽效果 一.鼠标事件 onclick ---------------鼠标点击事 ...

  5. vue 笔记,ref 及 $event 事件对象

    本文仅用作简单记录 ref : 在标签上添加 ref = “name” ,表示获取当前元素节点 <input type="text" ref="info" ...

  6. event事件对象

    事件对象event: 在触发DOM事件的时候都会产生一个对象 1.type:获取事件类型 2.target:获取事件目标 3.stopPropagation():组织事件冒泡 4.preventDef ...

  7. event事件对象和clientX,clientY

    一.event : 事件对象 , 当一个事件发生的时候,和当前这个对象发生的这个事件有关的一些详细的信息都会被临时保存到一个指定地方-event对象,供我们在需要的调用.如:飞机-黑匣子 事件对象必须 ...

  8. jquery之event与originalEvent的关系、event事件对象用法浅析

    在jquery中,最终传入事件处理程序的 event 其实已经被 jQuery 做过标准化处理, 其原有的事件对象则被保存于 event 对象的 originalEvent 属性之中, 每个 even ...

  9. 【js】event(事件对象)详解

    1.事件对象 Event 对象代表事件的状态,比如事件在其中发生的元素.键盘按键的状态.鼠标的位置.鼠标按钮的状态. 什么时候会产生Event 对象呢? 例如: 当用户单击某个元素的时候,我们给这个元 ...

随机推荐

  1. 阿里云ECS每天一件事D8:nginx1.7整合php5.4

    nginx本身的并不能解析php或者jsp,要转发给后端的php或者tomcat以及其他类似的应用程序服务器来提供服务. 首先我需要完成的配置是实现与php的整合,典型的配置信息如下: server ...

  2. [js - 算法可视化] 汉诺塔(Hanoi)演示程序

    前段时间偶然看到有个日本人很早之前写了js的多种排序程序,使用js+html实现的排序动画,效果非常好. 受此启发,我决定写几个js的算法动画,第一个就用汉诺塔. 演示地址:http://tut.ap ...

  3. 关于Struts2的碎碎念

    一:安全,还是安全 我入行比较晚,那会Spring MVC什么的都很流行了,一直觉得struts2作为一个Web MVC框架实在太笨重了点.所以虽然之前一直在用,但是其实没有真正研究过. 今天公司又遇 ...

  4. c++ 覆盖、重载、隐藏

    函数重载: 1.相同的范围内(即同一类中) 2.函数名相同: 3.参数不同: 4.virtual关键字可有可无: 函数覆盖:虚函数的功能.动态多态 (父类中必须有virtual)========派生类 ...

  5. PKU POJ 1006 Biorhythms (中国剩余定理)

    中国剩余定理 x = ai (mod mi)  ai和mi是一组数,mi两两互质,求x 令Mi = m1*m2*~mk     其中,mi不包含在内. 因为mi两两互质,所以存在x和y, st   M ...

  6. 拿别人APP的IPA包及你看上的图片

    闲话不多说, 开工 在MacX下载Itools软件,并安装,直接在百度上搜也能找到.Itools挺强大的,我在这里推荐一下. 在Itools中点击资源库,如果你连接上你的iPhone,这个按钮就在右上 ...

  7. Spring注解与Spring与Struts2整合

    @Component @Controller @Service @Repository 四大注解作用基本一样,只是表象在不同层面 @Resource @Scope Struts2与Spring整合:1 ...

  8. [C#绘图]在半透明矩形上绘制字符串

    首先要绘制一个半透明的矩形,用到的方法当然是FillRectangle().这个函数在调用的时候除了要指明要绘制的矩形外,还要指明填充矩形的背景色.具体的方法就是在绘制矩形的时候传给它一个画刷Brus ...

  9. PHP将Excel导入数据库以及数据库数据导出至Excel

    一.导入 导入需要使用能读取Excel的组件,网上也有比较好的组件,这里分享我使用的:下载  提取码:vxyn.(注意两个文件有引用关系) <?php //传入要导入的Excel的文件名 fun ...

  10. XML中SystemID和PublicID的区别

    http://hi.baidu.com/binboot007/item/1533f91d52113d7c7b5f259c http://supportweb.cs.bham.ac.uk/documen ...