繁体   English   中英

事件驱动的编程:回调与消息轮询

[英]Event-driven programming: callback vs message polling

我一直以C ++程序员的身份研究OpenGL编程,并且看到了两种处理事件驱动编程的主要方法:消息轮询或回调函数。

  • 我看到本地Win32API使用了一个回调函数,该函数由DispatchMessage函数触发。

  • SDL(基于教程)还使用某种回调或类似回调的编程。

  • GLFW还使用回调。

  • SFML使程序员可以在代码中的任何地方(通常是循环地)轮询单个消息,从而形成消息循环。

  • 根据我所看到的,X Window系统也使用消息轮询。

显然,由于事件系统存在于突出的环境中,因此每个事件系统都必须具有优势。 我希望有人能告诉我每个优点和缺点。 我正在考虑编写一些程序,这些程序在很大程度上取决于事件驱动的编程,并且希望对采用哪种方法做出最佳决定。

这还不完整,但是这里有一些需要注意的事情...

我只将GL用于3D,并且在GUI方面并没有做太多事情。 对事件进行轮询非常普遍。 更准确地说,在主渲染循环中进行轮询,该循环处理队列中的所有事件,然后继续进行渲染。 这是因为您在收集所有事件并使用它们更新场景的3D状态后从头开始重新渲染每一帧的所有内容。 由于屏幕只能以有限的帧速率显示图像,因此在轮询过程中通常会休眠,因为任何状态更新都不会显示,直到更晚才触发它们的事件。

  • 如果您要完全按照事件发生的方式处理事件(例如在绘制过程中途进行),那么您就有竞争条件。 处理这个问题可能是不必要的。

  • 如果您要设置动画,那么您已经有一个循环,而相比之下,轮询则是微不足道的成本。

  • 如果您的事件很少发生,那么您就不需要经常重新绘制,因此使线程处于活动状态并进行轮询会降低效率。

  • 如果事件堆积而您又为每个事件重新绘制,那将是非常糟糕的。 您可能会发现重新绘制的频率比使用循环处理所有事件并渲染一次的频率更高。

我认为轮询的主要问题是针对未激活的窗口。 假设您将GL应用程序最小化。 您知道它不会收到任何事件,因此轮询是无用的。 事情就是这样。

另一个问题是响应延迟。 这对于捕获游戏中的鼠标移动之类的东西非常重要。 只要您以正确的顺序轮询事件(输入→更新→显示),通常就可以了。 但是,vsync可能会通过延迟帧的显示而使时序混乱。

我目前正在基于openglevdev为Linux创建轻量级的GUI库。

C语言开发的第一个程序使我能够实现消息体系结构,这受多线程通信的管道用法启发。

第二,在c ++中 ,我仅使用回调,但是linux中的evdev堆栈是消息驱动的。

我的结论是,对于外围设备(例如:鼠标)而言,其触发中断的速度比程序响应速度更快,您需要一个fifo层(通常是一个管道)来使两个上下文之间的通信异步。 因此:消息只是在多线程环境中的异步缓冲回调。

您也可以使用回调fifo来缓冲事件。 但是在线程之间组织变量并不总是那么容易(信号量,锁定等)。 使用消息作为唯一的进程间同步机制有助于清除这一点。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM