事件驱动编程:回调与消息轮询
Event-driven programming: callback vs message polling
作为一名C++程序员,我一直在研究OpenGL编程,并了解了处理事件驱动编程的两种主要方法:消息轮询或回调函数。
-
我看到本机Win32API使用了一个回调函数,该函数由DispatchMessage函数触发。
-
SDL(基于教程)也使用某种回调或类似回调的编程。
-
GLFW也使用回调。
-
SFML允许程序员在代码的任何地方轮询单个消息,通常是在一个循环中,形成消息循环。
-
基于我所看到的,X Window系统也使用消息轮询。
显然,由于事件系统存在于突出的环境中,每个系统都必须具有优势。我希望有人能告诉我每种方法的优点和缺点。我正在考虑编写一些在很大程度上依赖于事件驱动编程的程序,并希望在选择哪条道路上做出最佳决定。
这并不完整,但我想到了一些事情。。。
我只在3D中使用过GL,在GUI方面没有做太多工作。对事件进行投票是很常见的。更准确地说,在主渲染循环中进行轮询,该循环处理队列中的所有事件,然后继续渲染。这是因为在收集所有事件并使用它们更新场景的3D状态后,可以在每帧从头开始重新渲染所有内容。由于屏幕只能以有限的帧速率显示图像,因此在轮询期间睡眠也是很常见的,因为即使事件提前触发,任何状态更新也要晚些时候才会显示。
-
如果你要完全按照事件发生的方式处理事件,比如绘制的中途,那么你就有了比赛条件。处理这个问题可能是不必要的。
-
如果你有任何动画,那么你已经有了一个循环,相比之下,轮询是一个微不足道的成本。
-
如果你的事件非常罕见,那么你不需要经常重新绘制,所以让线程处于活动状态和轮询有点效率。
-
如果事件堆积起来,而你又在为每一个事件重新绘制,那就太糟糕了。您可能会发现,与使用循环处理所有事件并渲染一次相比,重新绘制的频率更高。
我认为民意调查的主要问题是不活跃的窗口没有得到关注。假设您最小化GL应用程序。你知道它不会接收任何事件,所以轮询是无用的。绘画也是如此。
另一个问题是响应延迟。这对于像在游戏中捕捉鼠标移动这样的东西来说是非常重要的。只要您按正确顺序轮询事件(输入→使现代化→display)这通常是可以的。然而,vsync可能会延迟显示帧,从而扰乱时序。
我目前正在为linux创建基于opengl
和evdev
的轻量级GUI库。
第一个是在C中开发的,受pipe用于多线程通信的启发,我实现了消息体系结构。
对于第二个,在c++中,我只使用回调,但linux中的evdev
堆栈是消息驱动的。
我的结论是,对于外围设备(例如:鼠标),它可以比程序更快地触发中断,你需要一个fifo层(通常是一个管道),使两个上下文之间的通信异步。因此:消息只是多线程环境中的异步缓冲回调。
您也可以使用回调fifo来缓冲您的事件。但是,在线程之间组织变量并不总是那么容易(信号量、锁定等)。使用消息作为唯一的进程间同步机制有助于澄清这一点。
- 架构决策:返回std::future还是提供回调
- 正在为Xtensa simcall函数编写回调函数
- 如何在C++中使用非静态成员函数作为回调函数
- FLTK:按下哪个按钮 - 将数字传递给按钮的回调 (lambda)
- 在简单示例中,Python3 + ctypes 回调会导致内存泄漏
- 用于在回调中调用解析器的设计模式
- 如何使用C++对象的成员函数作为 C 样式回调?
- Java从C++回调到C++回调
- 如何将成员函数作为回调参数传递给需要"typedef-ed"自由函数指针的函数?
- 从不同的 cpp 调用回调函数会导致bad_function_call
- pcap_handler回调仅在使用 NPCAP v0.9991 时包含空数据包
- 哪些消息可以传递给低级鼠标挂钩回调函数
- ROS订阅者回调缺少消息
- 在状态栏上显示来自不同线程中回调的消息
- ZeroMQ是否有数据到达时的通知/回调事件/消息
- 事件驱动编程:回调与消息轮询
- WinAPI-带有自己回调的消息循环
- 使用Windows消息循环的回调实现
- 消息传递系统:回调可以是任何东西
- Windows:当我从本机代码回调到托管代码时,将显示“仅消息”窗口