浅析事件驱动与消息驱动

事件

简而言之就是发生了一件事情, 文件读完了, socket打开了, socket关闭了, 指的是一件发生了的事情.

消息

message, 我们可以认为就是简单的几个单词, 比如:张三告诉我文件读完了, 我获得了一个消息, 这个消息是张三告诉我的, 关于文件读完的消息.

事件驱动

监听一组或是多组事件, 一旦事件发生, 就巴拉巴拉巴拉…

libevent事件驱动

linux下多线程编程, 我们一般采用libevent事件驱动, 不断的监听多个事件, 实现多个worker的功能.

//  创建一个事件循环
event_base* m_ebase = event_base_new();
// 创建一个事件
event* m_event = event_new(m_ebase, fd, EV_READ | EV_PERSIST, cb, pThis);
// 开启循环
event_base_dispatch(m_ebase)

其中创建一个事件的时候, 我们给了一个fd, 需要监听的事件EV_READ | EV_PERSIST, 一个回调函数cb, pThis指的是回调的对象(参数). 当fd发生了我们监听的事件的时候, 就会回调到对应的函数. 通过添加多个fd, 我们可以为socket, 文件, 流等各种io添加监听函数, 不同事件的发生, 回调到不同的函数, 从而实现事件驱动.

消息驱动

windows的消息机制. 当鼠标点击,发生点击事件, windows检测到这一事件的发生, 随即发送一个消息到消息队列, 这个消息会附带一些数据, 地点啊, 坐标啊神马. windows线程在不断的轮询这个消息队列, 不断的获取消息, 获得这个消息之后做对应的处理, 从而实现消息驱动.

// 要保证自己消息队列已经创建了, 强制创建线程消息循环
MSG msg;
MSG msg;
while (true)
{
    PeekMessage(&msg, NULL, WM_USER, WM_USER, NULL);
    if (msg.message == WM_USER)
    {
    break;
    }
    else
    {
    PostMessage(NULL, WM_USER, NULL, NULL);
    }
}
// 开始循环
BOOL bRes = FALSE;
MSG msg;
while((bRes = GetMessage( &msg, NULL, 0, 0 )) != 0)
{
    if (bRes == -1)
    {
        break;
    }
    else
    {
        switch (msg.message)
        {
        case WM_QUIT:
            {
                ExitThread(0);
                break;
            }
        default:
            {
                TranslateMessage(&msg);
                DispatchMessage(&msg);
                break;
            }

        }
    }
}

// 发送一个消息
::PostThreadMessage(m_ThreadID, WM_QUIT, NULL, NULL);

总结

个人认为事件驱动和消息驱动并没有本质的区别, windows为了降低耦合, 大量使用的消息驱动, 但是消息发生的本质还是事件的发生, 然后由事件转化为消息, 源头还是一致的.

发表评论

电子邮件地址不会被公开。 必填项已用*标注