事件仅用于GUI编程吗?
当另一件事发生某些事情时,您如何处理普通的后端编程?
事件仅用于GUI编程吗?
当另一件事发生某些事情时,您如何处理普通的后端编程?
Answers:
不。它们对于实现Observers并确保类禁止修改很方便。
假设我们有一个注册新用户的方法。
public void Register(user) {
db.Save(user);
}
然后有人决定应该发送电子邮件。我们可以这样做:
public void Register(user) {
db.Save(user);
emailClient.Send(new RegistrationEmail(user));
}
但是我们刚刚修改了一个本应禁止修改的类。对于这种简单的伪代码来说可能不错,但是可能会使生产代码疯狂。这种方法需要30行代码才与创建新用户的最初目的几乎没有关系?
让类执行其核心功能并引发一个事件来告知正在侦听的用户,该用户会更好,他们可以采取所需的任何操作(例如发送电子邮件)。
public void Register(user) {
db.Save(user);
RaiseUserRegisteredEvent(user);
}
这样可以使我们的代码干净灵活。OOP中经常被忽略的部分之一是类之间相互发送消息。事件是这些消息。
不。
非GUI逻辑中使用的事件的经典示例是数据库触发器。
触发器是在发生给定事件(INSERT,DELETE等)时执行的代码。对我来说似乎是一件大事。
这是事件的维基百科定义:
在计算中,事件是软件可以识别的动作或事件,可以由软件处理。计算机事件可以由系统,用户或其他方式生成或触发。通常,事件是与程序流程同步处理的,也就是说,软件可能具有一个或多个处理事件的专用位置,通常是事件循环。事件源包括用户,该用户可以通过例如键盘上的击键与软件进行交互。另一个来源是硬件设备,例如计时器。软件还可以将自己的事件集触发到事件循环中,例如,传达任务的完成情况。响应事件而改变其行为的软件通常被认为是事件驱动的,目的是实现交互。
并非所有事件都是用户生成的。有些是由计时器生成的,例如crontab的计时器,是由数据库INSERT生成的,就像我之前提到的那样。
该定义还指出,某些程序或系统是“事件驱动的,通常以交互性为目标”,从中可以推论出事件的目的或用途不仅是为了提供交互性,而且还常常是为了提供交互性(例如GUI) (但不一定是GUI,因为CLI程序也可以是交互式的)。
实际上,基于事件的编程也用于高性能的服务器编程。
在典型的服务器工作负载下,处理结果的大部分时间实际上来自I / O。例如,从(7200 RPM)硬盘驱动器中提取数据最多可能需要8.3 ms。对于现代GHz处理器,这相当于约100万个时钟周期。如果CPU每次都在等待数据(不执行任何操作),我们将失去很多时钟周期。
传统的编程技术通过引入多个线程来解决此问题。CPU尝试同时运行数百个线程。但是,该模型的问题在于,每次CPU切换线程时,都需要数百个时钟周期才能进行上下文切换。上下文切换是指CPU将线程本地内存复制到CPU的寄存器中,并将旧线程的寄存器/状态存储到RAM中。
另外,每个线程必须用完一定数量的内存来存储其状态。
如今,人们一直在推动具有单线程且循环运行的服务器。然后,将工作推送到消息泵上,该消息泵充当单个线程的队列(非常类似于UI线程)。CPU无需等待工作完成,而是为硬盘驱动器访问之类的事件设置回调事件。这减少了上下文切换。
这种服务器的最佳示例是Node.js,它已被证明能够使用适度的硬件处理100万个并发连接,而Java / Tomcat服务器则要花费数千美元。
事件在网络编程中(例如Nginx)也被大量使用,以避免昂贵的繁忙等待循环,而是提供一个干净的接口来确切地知道何时可以进行某些操作(I / O,紧急数据等)。这也是解决C10k问题的方法。
基本思想是为操作系统提供一组套接字(即网络连接)来监视事件,这些套接字是所有事件还是您特别感兴趣的事件(例如,可读取的数据);当操作系统在列表中的一个套接字上检测到此类活动时,您将收到API所寻找事件的通知,然后您必须对该事件的来源进行分类并采取相应措施。
现在,这是一个低层次的抽象视图,而且很难很好地进行扩展。但是,有很多更高层次的框架甚至可以跨平台地处理这些问题:我想到了Twisted for Python,Boost.Asio for C ++或libevent forC。
对于非嵌入式系统,但是我在C#中所做的是SCADA系统。当卸载负载时,有许多事件与仓库中发生的事情相关,这是系统生成的事件的一部分,而另一部分是将新状态写入数据库。我们当然有一些GUI客户端,但这只是为了显示反映仓库状态的数据库状态。因此,它是基于事件和线程的后端服务器软件。发展颇具挑战性。