事件驱动处理
事件驱动处理(Event-driven processing)是指在持续事务管理过程中,进行决策的一种策略,即跟随当前时间点上出现的事件,调动可用资源,执行相关任务,使不断出现的问题得以解决,防止事务堆积的处理过程。
基本介绍
- 中文名:事件驱动处理
- 外文名:Event-driven processing
- 涉及学科:信息科学
- 套用:自动化
- 过程:持续事务管理过程
- 优点:防止事务堆积
基本定义
所谓事件驱动处理,简单地说就是你点什幺按钮(即产生什幺事件),电脑执行什幺操作(即调用什幺函式)。当然事件不仅限于用户的操作。事件驱动的核心自然是事件。
从事件角度说,事件驱动程式的基本结构是由一个事件收集器、一个事件传送器和一个事件处理器组成。
事件收集器专门负责收集所有事件,包括来自用户的(如滑鼠、键盘事件等)、来自硬体的(如时钟事件等)和来自软体的(如作业系统、应用程式本身等)。
事件传送器负责将收集器收集到的事件分发到目标对象中。
事件处理器做具体的事件回响工作,它往往要到实现阶段才完全确定,因而需要运用虚函式机制(函式名往往取为类似于HandleMsg的一个名字)。对于框架的使用者来说,他们唯一能够看到的是事件处理器。这也是他们所关心的内容。
视图(即我们通常所说的“视窗”)是“事件驱动”应用程式的另一个要元。它是我们所说的事件传送器的目标对象。视图接受事件并能够对其进行处理。当我们将事件传送到具体的视图时,实际上我们完成了一个根本性的变化:从传统的流线型程式结构到事件触发方式的转变。这样应用程式具备相当的柔性,可以应付种种离散的、随机的事件。
用户动作产生的事件
用户动作 | 源对象 | 事件类 |
单击按钮 | JButton | ActionEvent |
单击複选框 | JCheckBox | ItemEvent, ActionEvent |
单击单选框 | JRadioButton | ItemEvent, ActionEvent |
在文本框里按回车键 | JTextField | ActionEvent |
选择一个新项目 | JComboBox | ItemEvent, ActionEvent |
视窗打开、关闭等 | Window | WindowEvent |
滑鼠按下、释放等 | Component | MouseEvent |
键盘按钮、释放等 | Component | KeyEvent |
要理解事件驱动和程式,就需要与非事件驱动的程式进行比较。实际上,现代的程式大多是事件驱动的,比如多执行绪的程式,肯定是事件驱动的。早期则存在许多非事件驱动的程式,这样的程式,在需要等待某个条件触发时,会不断地检查这个条件,直到条件满足,这是很浪费cpu时间的。而事件驱动的程式,则有机会释放cpu从而进入睡眠态(注意是有机会,当然程式也可自行决定不释放cpu),当事件触发时被作业系统唤醒,这样就能更加有效地使用cpu.
再说什幺是事件驱动的程式。一个典型的事件驱动的程式,就是一个死循环,并以一个执行绪的形式存在,这个死循环包括两个部分,第一个部分是按照一定的条件接收并选择一个要处理的事件,第二个部分就是事件的处理过程。程式的执行过程就是选择事件和处理事件,而当没有任何事件触发时,程式会因查询事件伫列失败而进入睡眠状态,从而释放cpu。
事件驱动的程式,必定会直接或者间接拥有一个事件伫列,用于存储未能及时处理的事件。
事件驱动的程式的行为,完全受外部输入的事件控制,所以,事件驱动的系统中,存在大量这种程式,并以事件作为主要的通信方式。
事件驱动的程式,还有一个最大的好处,就是可以按照一定的顺序处理伫列中的事件,而这个顺序则是由事件的触发顺序决定的,这一特性往往被用于保证某些过程的原子化。
目前windows,linux,nucleus,vxworks都是事件驱动的,只有一些单片机可能是非事件驱动的。
Windows作业系统下
由于Windows本身是基于“事件驱动”模型的。因而在Windows作业系统下实现应用程式框架有相当的便利。在事件驱动程式的基本单元中,事件收集器已经由Windows系统完成;事件传送器也已经由Windows完成了部分内容。之所以是部分而非完全是因为Windows是用C语言实现的,而不是C++。由于没有对象,Windows将事件传送到所谓的“视窗函式”中(儘管不是传送到具体的对象,但应该说这是面向对象方式实现的一个变体)。要感谢Windows做了这件事。确定事件的目标所要做的工作的複杂可能要超出我们的想像。
wxWidgets的中所有可以处理事件的类都继承自wxEvtHandler,其中包含frames,buttons,menus,even documents,所有的窗体类(即从wxWindow继承的类)和程式类(application class).
这些类可以有一个事件表,用来绑定事件和被调用的函式(handler functions).
过程
- 建立一个静态事件表(即编译时生成的事件表)的操作步骤
- 建立一个新类(直接或间接从wxEvtHandler继承)
- 为每个要处理的事件声明被调用的函式
- 在被处理的事件所在的类的声明中加入宏DECLARE_EVENT_TABLE
- 在宏BEGIN_EVENT_TABLE... END_EVENT_TABLE(就是事件表)中将函式与枚举的数字绑定(因为产生该类型的事件的按钮不唯一,要用枚举数来区分);有些事件不必与枚举数绑定,因为产生该类型的事件的对象可以确定(比如就是this).
例
一个事件表
BEGIN_EVENT_TABLE(MyFrame,wxFrame)
EVT_MENU (wxID_ABOUT,MyFrame::OnAbout)
EVT_MENU (wxID_EⅪT,MyFrame::OnQuit)
EVT_SIZE (MyFrame::OnSize)
//不必与枚举数绑定,因为产生该类型的事件的对象是this
EVT_BUTTON (wxID_OK,MyFrame::OnButtonOK)
END_EVENT_TABLE()
注
在事件中指定被绑定的数字,wxWidgets会将其映射到对应的函式,并调用函式
所有在事件表中被绑定的函式有相似的形式:返回值都是void,不是virtual函式,参数为wxCommandEvent类型
事件驱动处理程式
为需要处理的事件编写相应的事件处理程式。要理解事件驱动和程式,就需要与非事件驱动的程式进行比较。实际上,现代的程式大多是事件驱动的,比如多执行绪的程式,肯定是事件驱动的。早期则存在许多非事件驱动的程式,这样的程式,在需要等待某个条件触发时,会不断地检查这个条件,直到条件满足,这是很浪费cpu时间的。而事件驱动的程式,则有机会释放cpu从而进入睡眠态(注意是有机会,当然程式也可自行决定不释放cpu),当事件触发时被作业系统唤醒,这样就能更加有效地使用cpu。
为需要处理的事件编写相应的事件处理程式。代码在事件发生时执行。
delphi和java编程特点
n事件(event)表示程式某件事发生的信号。事件分为:
o外部事件:由外部用户动作产生的事件。例如,点击滑鼠、按键盘。
o内部事件:由系统内部产生的事件。例如,定时器事件。
n源对象(source object)是产生事件的对象。
事件处理驱动的一般步骤
1、确定回响事件的元素
2、为指定元素确定需要回响的事件类型
3、为指定元素的指定事件编写相应的事件处理程式
4、将事件处理程式绑定到指定元素的指定事件

每个事件对象包含与该事件相关的属性。getSource()方法可以获取事件的源对象。
事件驱动处理库
通常,我们写伺服器处理模型的程式时,有以下几种模型:
(1)每收到一个请求,创建一个新的进程,来处理该请求;
(2)每收到一个请求,创建一个新的执行绪,来处理该请求;
(3)每收到一个请求,放入一个事件列表,让主进程通过非阻塞I/O方式来处理请求
上面的几种方式,各有千秋,
第(1)种方法,由于创建新的进程的开销比较大,所以,会导致伺服器性能比较差,但实现比较简单。
第(2)种方式,由于要涉及到执行绪的同步,有可能会面临死锁等问题。
第(3)种方式,在写应用程式代码时,逻辑比前面两种都複杂。
综合考虑各方面因素,一般普遍认为第(3)种方式是大多数网路伺服器採用的方式——事件驱动处理库。