概述

异步通知是客户端开发中常见的需求,比如在一个网络处理线程中要通知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. Java Web学习笔记---用GET实现搜索引擎

    今天做了一个实验,关于Servlet的.使用GET实现搜索引擎.因自己没有搜索引擎数据库,所以使用了Yahoo提供的Search API. 浏览效果如下图: 现在雅虎推出了新的Search API-- ...

  2. New Plan!

    很久无写过blogs,荒废得差不多了,在博客园虽开bolg 5年多,但由于自己工作的问题,从开始的热情记录,到冷却冰冻,再到现在重拾起来,有一番感受:从大学刚毕业的制作网页菜鸟,开始接触DIV,CSS ...

  3. 【Sorting Collection】

    排序集锦 各种排序算法,总结一下,一直在遗忘...... [冒泡排序] 就是下面这个鬼啦: c实现代码(升序): #include<stdio.h> void BubbleSort(int ...

  4. linux虚拟系统determining IP information for eth0...failed

    这几天学习老男孩Linux运维 其中有一节视频进行连接网络时出现: 上网搜了很多方法,包括:向如下三个文件中添加如下代码 check_link_down() { return 1; } (1)/etc ...

  5. php使用openssl进行Rsa长数据加密(117)解密(128) 和 DES 加密解密

    PHP使用openssl进行Rsa加密,如果要加密的明文太长则会出错,解决方法:加密的时候117个字符加密一次,然后把所有的密文拼接成一个密文:解密的时候需要128个字符解密一下,然后拼接成数据. 加 ...

  6. 关于C#中的 static

    一:感受 做商业项目才能更深刻和彻底的探索到技术的原理与真实面貌.以前在学校里面的时候这些C Sharp的基本语法,数据结构,面向对象背的滚瓜乱熟,那真得是背的!无论是从概念从理论上面来谈还是写一个小 ...

  7. codeforces682A

    题目:http://codeforces.com/problemset/problem/682/A 理解: 比较简单的一道题 思路很重要 #include<iostream>//***** ...

  8. 转载自lanceyan: 一致性hash和solr千万级数据分布式搜索引擎中的应用

    一致性hash和solr千万级数据分布式搜索引擎中的应用 互联网创业中大部分人都是草根创业,这个时候没有强劲的服务器,也没有钱去买很昂贵的海量数据库.在这样严峻的条件下,一批又一批的创业者从创业中获得 ...

  9. Markdown编辑器:Typora

    现在网上的Markdown有很多,各有各的特色,同时也有各自的缺点.比如有的传图片比较麻烦,有的导出pdf需要付费,有的数学公式编辑比较麻烦等等...... 而最近接触到Typora,发现这真是一款良 ...

  10. tab 切换写法

    <script>        var oUL = document.getElementById('aboutTab-ul');        var oLi = oUL.getElem ...