概述

异步通知是客户端开发中常见的需求,比如在一个网络处理线程中要通知UI线程更新等等。

通常在Windows编程中,为了方便,我们一般会向UI线程的窗口句柄Post/Send一个窗口消息从而达到将非UI线程的事件切换到UI线程处理的目的。

在SOUI引入通知中心以前要在SOUI中处理非UI线程事件我也推荐用上面的方法。

使用窗口消息至少有以下两个不足:

1、需要在线程中持有一个窗口句柄。

2、发出的消息只能在该窗口句柄的消息处理函数里处理。

SNotifyCenter

最新的SOUI引入了一个新的单例对象:SNotifyCenter,专门用来处理这类问题。

新的SNotifyCenter解决了窗口消息存在的上面的两个问题:

1、通过使用全局单例,SNotifyCenter可以在代码任意位置获取它的指针(前提当然是要在它的生命周期内);

2、使用SNotifyCenter产生的通知采用SOUI的事件系统来派发,通过结合SOUI的事件订阅系统,用户可以在任意位置处理发出的事件。

在介绍如何使用SNotifyCenter前,先看一下NotifyCenter.h的代码:

 #pragma once

 #include <core/SSingleton.h>

 namespace SOUI
{
template<class T>
class TAutoEventMapReg
{
typedef TAutoEventMapReg<T> _thisClass;
public:
TAutoEventMapReg()
{
SNotifyCenter::getSingleton().RegisterEventMap(Subscriber(&_thisClass::OnEvent,this));
} ~TAutoEventMapReg()
{
SNotifyCenter::getSingleton().UnregisterEventMap(Subscriber(&_thisClass::OnEvent,this));
} protected:
bool OnEvent(EventArgs *e){
T * pThis = static_cast<T*>(this);
return !!pThis->_HandleEvent(e);
}
}; class SOUI_EXP SNotifyCenter : public SSingleton<SNotifyCenter>
, public SEventSet
{
public:
SNotifyCenter(void);
~SNotifyCenter(void); /**
* FireEventSync
* @brief 触发一个同步通知事件
* @param EventArgs *e -- 事件对象
* @return
*
* Describe 只能在UI线程中调用
*/
void FireEventSync(EventArgs *e); /**
* FireEventAsync
* @brief 触发一个异步通知事件
* @param EventArgs *e -- 事件对象
* @return
*
* Describe 可以在非UI线程中调用,EventArgs *e必须是从堆上分配的内存,调用后使用Release释放引用计数
*/
void FireEventAsync(EventArgs *e); /**
* RegisterEventMap
* @brief 注册一个处理通知的对象
* @param const ISlotFunctor &slot -- 事件处理对象
* @return
*
* Describe
*/
bool RegisterEventMap(const ISlotFunctor &slot); /**
* RegisterEventMap
* @brief 注销一个处理通知的对象
* @param const ISlotFunctor &slot -- 事件处理对象
* @return
*
* Describe
*/
bool UnregisterEventMap(const ISlotFunctor & slot);
protected:
void OnFireEvent(EventArgs *e); void ExecutePendingEvents(); static VOID CALLBACK OnTimer( HWND hwnd,
UINT uMsg,
UINT_PTR idEvent,
DWORD dwTime
); SCriticalSection m_cs; //线程同步对象
SList<EventArgs*> *m_evtPending;//挂起的等待执行的事件
DWORD m_dwMainTrdID;//主线程ID UINT_PTR m_timerID; //定时器ID,用来执行异步事件 SList<ISlotFunctor*> m_evtHandlerMap;
};
}

在这个文件中提供了两个类,一个就是SNotifyCenter,另一个是TAutoEventMapReg<T>。

可以看到SNotifyCenter中除构造外只有4个public方法:

FireEventSync, FireEventAsync用来触发事件。

RegisterEventMap,UnregisterEventMap则用来提供事件处理订阅。

如何使用SNotifyCenter?

1、在main中实例化SNotifyCenter。(不明白可以参考demo)

2、定义需要通过通知中心分发的事件类型,首先定义事件,然后向通知中心注册,参见下面代码:

 void CMainDlg::OnBtnStartNotifyThread()
{
if(IsRunning()) return;
SNotifyCenter::getSingleton().addEvent(EVENTID(EventThreadStart));
SNotifyCenter::getSingleton().addEvent(EVENTID(EventThreadStop));
SNotifyCenter::getSingleton().addEvent(EVENTID(EventThread)); EventThreadStart evt(this);
SNotifyCenter::getSingleton().FireEventSync(&evt);
BeginThread();
} void CMainDlg::OnBtnStopNotifyThread()
{
if(!IsRunning()) return; EndThread();
EventThreadStop evt(this);
SNotifyCenter::getSingleton().FireEventSync(&evt); SNotifyCenter::getSingleton().removeEvent(EventThreadStart::EventID);
SNotifyCenter::getSingleton().removeEvent(EventThreadStop::EventID);
SNotifyCenter::getSingleton().removeEvent(EventThread::EventID);
}

3、使需要处理通知中心分发的事件的对象从TAutoEventMapReg继承,实现事件的自动订阅(方便在事件映射表中统一处理事件),这一步是可选的,你也可以直接使用SOUI提供的事件订阅机制向通知中心订阅特定事件。

4、在事件映射表里处理事件(没有第3步时,则同样没有这一步)。

具体用法参见SOUI的demo。

第三十四篇:在SOUI中使用异步通知的更多相关文章

  1. Egret入门学习日记 --- 第十四篇(书中 5.4~5.6节 内容)

    第十四篇(书中 5.4~5.6节 内容) 书中内容: 总结 5.4节 内容重点: 1.如何编写自定义组件? 跟着做: 重点1:如何编写自定义组件? 文中提到了重要的两点. 好,我们来试试看. 第一步, ...

  2. 第二十八篇:SOUI中自定义控件开发过程

    在SOUI中已经提供了大部分常用的控件,但是内置控件不可能满足用户的所有要求,因此一个真实的应用少不得还要做一些自定义控件. 学习一个新东西,最简单的办法就是依葫芦画瓢.事实上在SOUI系统中内置控件 ...

  3. Android UI开发第三十四篇——SlidingPaneLayout

    SlidingPaneLayout也是系统支持的高级控件,是Android团对在2013 google IO大会期间更新的Support库(Version 13)中新加入的重要的功能.它支持左右滑动菜 ...

  4. 第三十四篇 Python面向对象之 反射(自省)

    什么是反射? 反射的概念是由Smith在1982年提出的,主要是指程序可以访问.检测和修改它本身状态或行为的一种能力(自省).这一概念的提出很快引发了计算机科学领域关于应用反射性的研究.它首先被程序语 ...

  5. C++第三十四篇 -- 安装Windows Driver后,编译以前项目出现打不开lib文件

    VS2017默认是没有安装WDK的,但是我们写驱动文件的话需要用到WDK.不过安装了WDK后,发现以前一些正常的项目在Release模式下编译会报LINK1104,无法打开.lib的错误 针对这个错误 ...

  6. Python之路(第三十四篇) 网络编程:验证客户端合法性

    一.验证客户端合法性 如果你想在分布式系统中实现一个简单的客户端链接认证功能,又不像SSL那么复杂,那么利用hmac+加盐的方式来实现. 客户端验证的总的思路是将服务端随机产生的指定位数的字节发送到客 ...

  7. 第三十四篇-Palette(调色板)的使用

    由于屏幕录制图片转换关系,不甚清晰,还是附上效果图 可以看出,上面文字和背景颜色确实会根据图片的变化而变化. 里面有3个组件,toolbar,textview,imageview,其中textview ...

  8. 第三十四章、PyQt中的输入部件:QComboBox组合框功能详解

    专栏:Python基础教程目录 专栏:使用PyQt开发图形界面Python应用 专栏:PyQt入门学习 老猿Python博文目录 一.概述 Designer中输入工具部件中的Combo Box组合框与 ...

  9. 第三十四篇 玩转数据结构——哈希表(HashTable)

    1.. 整型哈希函数的设计 小范围正整数直接使用 小范围负整数整体进行偏移 大整数,通常做法是"模一个素数"   2.. 浮点型哈希函数的设计 转成整型进行处理   3.. 字符串 ...

随机推荐

  1. Nginx笔记

    基础篇 关于Nginx Nginx是一款轻量级的Web 服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器.最早由俄罗斯的程序设计师Igor Sysoev所开发,并在一个BSD-like ...

  2. linux指令学习笔记(一)

    1. 查看目录下有什么文件/目录    > ls            //list列出目录的文件信息    > ls  -l 或ll   //list -list以“详细信息”查看目录文 ...

  3. 3种方法修改PHP时区

    PHP5.2.4之前的版本无需设置时区.下面是修改PHP时区的三个办法. 1.修改PHP.ini这个文件 找到date.timezone这行,去掉前面的分号,改成: date.timezone = A ...

  4. 防火墙iptables

    iptables命令可用于配置Linux的包过滤规则,常用于实现防火墙.NAT.咋一看iptables的配置很复杂,掌握规律后,其实用iptables完成指定任务并不难,下面我们通过具体实例,学习ip ...

  5. SQL Server 2008 R2 错误代码:233

    解决方法:打开SQL Server配置管理器,找到MSSQLSERVER的协议,启动TCP/IP和Named Pipes

  6. JSP内置对象之request对象【学习笔记】

    request对象是JSP中重要的对象,每个request对象封装着一次用户的请求,并且所有的请求参数都被封装在request对象中,因此request对象是获取请求参数的重要途径. 一.获取请求头与 ...

  7. iOS-关于使用其他应用打开本应用文档

    简介:本片文章是对官方文档的翻译,非常的感谢文章的翻译者:颐和园 官方地址:Document Interaction Programming Topics for iOS 文章的介绍内容: ***** ...

  8. WebService初学

    作为一个初学者,在遇到新的知识点的时候,搞清这个知识点的名称含义,是有必要的.那什么是WebService呢? 顾名思义,它是一个运行在web上的服务.这个服务通过网络为我们的程序提供服务方法.类似一 ...

  9. 给Excel2013添加WebADI的Oracle加载项

    大家都知道,在Excel2013的加载项中是找不到WebADI的加载项的,EBS貌似有一个补丁,这里讲手动设置的步骤: 打开一个下载的WebADI的模板: 依次打开菜单: 文件>选项>自定 ...

  10. redis 间断性耗时长问题解决

    我发现开发项目用的redis 隔一两分钟就出现 耗时问题,长达五秒.一开始以为是 redis 服务器不稳定,但运维测试发现redis稳定的,在高并发下最大耗时也就只有100毫秒左右,怎么也不可能达到5 ...