概述
异步通知是客户端开发中常见的需求,比如在一个网络处理线程中要通知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
namespace SOUI
{
template
class TAutoEventMapReg
{
typedef TAutoEventMapReg _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(this);
return !!pThis->_HandleEvent(e);
}
};
class SOUI_EXP SNotifyCenter : public SSingleton
, 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 *m_evtPending;//挂起的等待执行的事件
DWORD m_dwMainTrdID;//主线程ID
UINT_PTR m_timerID; //定时器ID,用来执行异步事件
SList m_evtHandlerMap;
};
}
在这个文件中提供了两个类,一个就是SNotifyCenter,另一个是TAutoEventMapReg。
可以看到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。
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年提出的,主要是指程序可以访问.检测和修改它本身状态或行为的一种能力(自省).这一概念的提出很快引发了计算机科学领域关于应用反射性的研究.它首先被程序语 ...
Python之路(第三十四篇) 网络编程:验证客户端合法性
一.验证客户端合法性 如果你想在分布式系统中实现一个简单的客户端链接认证功能,又不像SSL那么复杂,那么利用hmac+加盐的方式来实现. 客户端验证的总的思路是将服务端随机产生的指定位数的字节发送到客 ...
第三十四篇-Palette(调色板)的使用
由于屏幕录制图片转换关系,不甚清晰,还是附上效果图 可以看出,上面文字和背景颜色确实会根据图片的变化而变化. 里面有3个组件,toolbar,textview,imageview,其中textview ...
第三十四篇 玩转数据结构——哈希表(HashTable)
1.. 整型哈希函数的设计 小范围正整数直接使用 小范围负整数整体进行偏移 大整数,通常做法是"模一个素数" 2.. 浮点型哈希函数的设计 转成整型进行处理 3.. 字符串 ...
解剖SQLSERVER 第十四篇 Vardecimals 存储格式揭秘(译)
解剖SQLSERVER 第十四篇 Vardecimals 存储格式揭秘(译) http://improve.dk/how-are-vardecimals-stored/ 在这篇文章,我将深入研究 ...
JAVA之旅(三十四)——自定义服务端,URLConnection,正则表达式特点,匹配,切割,替换,获取,网页爬虫
JAVA之旅(三十四)--自定义服务端,URLConnection,正则表达式特点,匹配,切割,替换,获取,网页爬虫 我们接着来说网络编程,TCP 一.自定义服务端 我们直接写一个服务端,让本机去连接 ...
随机推荐
Xcode使错误停在出错代码上
创建异常断点 依次选择“Debug”>“Breakpoints”>“Create Execption Breakpoint”
js window对象
BOM的核心对象是window,它表示浏览器的一个实例. 在浏览器中,window对象是(1)通过JavaScript访问浏览器窗口的一个接口 (2)ECMAScript规定的Global对象 1.全 ...
Linux系统信息查看命令大全
系统# uname -a # 查看内核/操作系统/CPU信息# head -n 1 /etc/issue # 查看操作系统版本# cat /proc/cpuinfo # 查看CPU信息# hostna ...
leetcode 96 Unique Binary Search Trees ----- java
Given n, how many structurally unique BST's (binary search trees) that store values 1...n? For examp ...
leetcode:Path Sum (路径之和) 【面试算法题】
题目: Given a binary tree and a sum, determine if the tree has a root-to-leaf path such that adding up ...
leetcode6	Reverse Words in a String 单词取反
Reverse Words in a String 单词取反 [email protected] Question: Given an input string s, reverse the ...
table 西边框样式
table { border-collapse: collapse; border: none; width: 200p ...
poj 3187 Backward Digit Sums(穷竭搜索dfs)
Description FJ and his cows enjoy playing a mental game. They write down the numbers to N ( <= N ...
c# mouseenter mousemove区别?
onmousedown 当用户用任何鼠标按钮单击对象时触发. onmouseenter 当用户将鼠标指针移动到对象内时触发. onmouseleave 当用户将鼠标指针移出对象边界时触发. onmou ...