第三十四篇:在SOUI中使用异步通知
概述
异步通知是客户端开发中常见的需求,比如在一个网络处理线程中要通知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中使用异步通知的更多相关文章
- Egret入门学习日记 --- 第十四篇(书中 5.4~5.6节 内容)
第十四篇(书中 5.4~5.6节 内容) 书中内容: 总结 5.4节 内容重点: 1.如何编写自定义组件? 跟着做: 重点1:如何编写自定义组件? 文中提到了重要的两点. 好,我们来试试看. 第一步, ...
- 第二十八篇:SOUI中自定义控件开发过程
在SOUI中已经提供了大部分常用的控件,但是内置控件不可能满足用户的所有要求,因此一个真实的应用少不得还要做一些自定义控件. 学习一个新东西,最简单的办法就是依葫芦画瓢.事实上在SOUI系统中内置控件 ...
- Android UI开发第三十四篇——SlidingPaneLayout
SlidingPaneLayout也是系统支持的高级控件,是Android团对在2013 google IO大会期间更新的Support库(Version 13)中新加入的重要的功能.它支持左右滑动菜 ...
- 第三十四篇 Python面向对象之 反射(自省)
什么是反射? 反射的概念是由Smith在1982年提出的,主要是指程序可以访问.检测和修改它本身状态或行为的一种能力(自省).这一概念的提出很快引发了计算机科学领域关于应用反射性的研究.它首先被程序语 ...
- C++第三十四篇 -- 安装Windows Driver后,编译以前项目出现打不开lib文件
VS2017默认是没有安装WDK的,但是我们写驱动文件的话需要用到WDK.不过安装了WDK后,发现以前一些正常的项目在Release模式下编译会报LINK1104,无法打开.lib的错误 针对这个错误 ...
- Python之路(第三十四篇) 网络编程:验证客户端合法性
一.验证客户端合法性 如果你想在分布式系统中实现一个简单的客户端链接认证功能,又不像SSL那么复杂,那么利用hmac+加盐的方式来实现. 客户端验证的总的思路是将服务端随机产生的指定位数的字节发送到客 ...
- 第三十四篇-Palette(调色板)的使用
由于屏幕录制图片转换关系,不甚清晰,还是附上效果图 可以看出,上面文字和背景颜色确实会根据图片的变化而变化. 里面有3个组件,toolbar,textview,imageview,其中textview ...
- 第三十四章、PyQt中的输入部件:QComboBox组合框功能详解
专栏:Python基础教程目录 专栏:使用PyQt开发图形界面Python应用 专栏:PyQt入门学习 老猿Python博文目录 一.概述 Designer中输入工具部件中的Combo Box组合框与 ...
- 第三十四篇 玩转数据结构——哈希表(HashTable)
1.. 整型哈希函数的设计 小范围正整数直接使用 小范围负整数整体进行偏移 大整数,通常做法是"模一个素数" 2.. 浮点型哈希函数的设计 转成整型进行处理 3.. 字符串 ...
随机推荐
- Ubuntu提示卷boot仅剩0字节的硬盘空间,解决办法
查看当前安装的linux内核版本号 dpkg --get-selections |grep linux-image 查看当前使用的内核版本号 uname -a 卸载不需要的内核 sudo apt-ge ...
- eclispe+axis2+webservice入门
配置eclipse相关插件并启动axis2: http://blog.csdn.net/pilihaotian/article/details/52513697 这里你可能会遇到使用eclipse 启 ...
- vim的编译安装及其插件YouCompleteMe安装
相关的环境: win 7 x64 vs2013 community python 2.7.10 AMD64 python 3.5 AMD64 LLVM 3.5 cmake 3.5 YouCompl ...
- YII 错误 SQLSTATE[HY000] [2002] No such file or directory
在使用yii的yii\db\Connnection时发生错误 <?php namespace app\controllers; use yii\web\Controller; use yii\d ...
- Netty里的设计模式
最近在撸 Netty 源码,发现了一些模式,顺手做个笔记. 分析版本是4.0 1. 构造器模式 ServerBootstrap 和 Bootstrap 的构建 2. 责任链设计模式 pipeline ...
- $.extend()和 $.fn.extend()
1 $.extend() jQuery.extend(): Merge the contents of two or moreobjects together into the first ...
- json和jsonp
JSON是一种数据交换格式! JSONP是一种依靠开发人员的聪明才智创造出的一种非官方跨域数据交互协议! 一般使用JSON来传数据,靠JSONP来跨域. JSON的优点: 1.基于纯文本, ...
- Linux kernel 文件夹说明
Linux 内核代码的目录结构 arch: 包含和硬件体系相关的的代码,每种硬件平台占一个相应的目录,如i386,arm, arm64, powerpc,mips等. block: 块设备驱动程序I/ ...
- Mac挂载NTFS移动硬盘读取VMware虚拟机文件
一.Mac 挂载NTFS移动硬盘进行读写操作 (Read-only file system) 注意如下图所示先卸载,然后按照下图的命令进行挂载.然后cd /opt/003_vm/ &&am ...
- C#多线程 线程的启动
在实例化Thread的实例,需要提供一个委托,在实例化这个委托时所用到的参数是线程将来启动时要运行的方法.在.net中提供了两种启动线程的方式,一种是不带参数的启动方式,另一种是带参数的启动的方式. ...