简单记录自己对于 消息驱动 和 事件驱动的理解。
关于这二者的具体区别,于实现上来说,二者都是 注册绑定,然后交付执行。
消息驱动模型在注册的时候仅仅注册一个回调函数作为处理函数。
而事件驱动模型则需要注册多个函数作为处理函数。
消息驱动模型由于处理函数只有一个的缘故,
故需要在回调函数中使用switch等手段,
对消息进行派发并具体处理。
而事件驱动模型则需要在各个回调函数中处理各自的事物。
所以从框架角度说,
消息驱动模型的复用性高于事件驱动模型,
或者说事件驱动模型一般用于处理某个特定的问题。
而造成这种情形的原因是,
消息驱动模型不需要知道具体的消息含义,
而事件驱动模型则需要知道具体的事件含义,
否则无法通过回调函数处理。
细节说明:
事件驱动机制跟消息驱动机制相比
9102年,重新审视 事件驱动 与 消息驱动。
需要理解的是这三个词的含义。
首先聊一下何为驱动,
驱动具象化理解就像开车一样,点一脚油就动一下。
抽象的代码表示驱动一词
func driver() {
while(condition) {
watch(worker);
}
}
何为事件,字面意思,
意思是比较重大、对一定的人群会产生一定影响的事情。
简单用代码描述如下
// 用户定义
register(read_fn, flag);
// 用户定义
func read_fn(bytes []) {
dosomething();
}
// 框架提供
func register(do, flag) {
fn[flag] = do;
}
// 框架提供
func watch(worker) {
// 例子,此处也可能是 epoll poll select 等
// 或者是经过包装的高级模型
which= WaitForMultipleObjecct();
fn[ctx[which].flag](ctx[which].bytes);
}
何为消息,同字面意思
// 用户定义
func worker(msg) {
switch(msg) {
case 0: break;
case 1: break;
default: break;
//....
}
}
// 框架提供
func watch(worker) {
// 阻塞队列常用于实现消息队列和事件队列
msg = GetHeadFromBlockQueue();
worker(msg);
}
上述就是常见框架的缩影,具体到日常框架中,再对比一下使用方式,如下。
例如 libuv 或libevent的使用示例
struct event* ev_listen = event_new(xxx);
event_add(ev_listen, NULL);
bufferevent_setcb(bev, socket_read_cb, NULL, event_cb, arg);
// 事件循环
event_base_dispatch(base);
再例如
// 省略注册窗口类时对于消息分发函数注册等代码。
// ....
// 消息泵
BOOL ret;
while((ret=GetMessage(&msg,hWnd,0,0))!=0) {
if(ret==-1) {
//handle the error and possibly exit
return -1;
}
else {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
实现上二者差异并不算大,例如消息驱动中,可以向消息队列中压入消息唤醒,而事件驱动中也可以从外部写fd 唤醒。
事件的作用范围为系统提供的事件种类。
消息的作用范围为系统提供的消息种类。
可以实现自定义消息,却无法自定义事件。
当然消息本身可以看做是一种特殊的事件。
二者应用领域有一定交集,各有所长。
事件驱动模型主要应用于 网络框架,有着固定的几大基础事件。
[被]连接,[被]断开,收,发。
消息驱动模型常见于 窗口框架。需要应付种类繁多的消息。
WM_xxxxx

9103

被折叠的 条评论
为什么被折叠?



