第三十四篇:在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的代码:
1 #pragma once 2 3 #include <core/SSingleton.h> 4 5 namespace SOUI 6 { 7 template<class T> 8 class TAutoEventMapReg 9 { 10 typedef TAutoEventMapReg<T> _thisClass; 11 public: 12 TAutoEventMapReg() 13 { 14 SNotifyCenter::getSingleton().RegisterEventMap(Subscriber(&_thisClass::OnEvent,this)); 15 } 16 17 ~TAutoEventMapReg() 18 { 19 SNotifyCenter::getSingleton().UnregisterEventMap(Subscriber(&_thisClass::OnEvent,this)); 20 } 21 22 protected: 23 bool OnEvent(EventArgs *e){ 24 T * pThis = static_cast<T*>(this); 25 return !!pThis->_HandleEvent(e); 26 } 27 }; 28 29 class SOUI_EXP SNotifyCenter : public SSingleton<SNotifyCenter> 30 , public SEventSet 31 { 32 public: 33 SNotifyCenter(void); 34 ~SNotifyCenter(void); 35 36 /** 37 * FireEventSync 38 * @brief 触发一个同步通知事件 39 * @param EventArgs *e -- 事件对象 40 * @return 41 * 42 * Describe 只能在UI线程中调用 43 */ 44 void FireEventSync(EventArgs *e); 45 46 /** 47 * FireEventAsync 48 * @brief 触发一个异步通知事件 49 * @param EventArgs *e -- 事件对象 50 * @return 51 * 52 * Describe 可以在非UI线程中调用,EventArgs *e必须是从堆上分配的内存,调用后使用Release释放引用计数 53 */ 54 void FireEventAsync(EventArgs *e); 55 56 57 /** 58 * RegisterEventMap 59 * @brief 注册一个处理通知的对象 60 * @param const ISlotFunctor &slot -- 事件处理对象 61 * @return 62 * 63 * Describe 64 */ 65 bool RegisterEventMap(const ISlotFunctor &slot); 66 67 /** 68 * RegisterEventMap 69 * @brief 注销一个处理通知的对象 70 * @param const ISlotFunctor &slot -- 事件处理对象 71 * @return 72 * 73 * Describe 74 */ 75 bool UnregisterEventMap(const ISlotFunctor & slot); 76 protected: 77 void OnFireEvent(EventArgs *e); 78 79 void ExecutePendingEvents(); 80 81 static VOID CALLBACK OnTimer( HWND hwnd, 82 UINT uMsg, 83 UINT_PTR idEvent, 84 DWORD dwTime 85 ); 86 87 SCriticalSection m_cs; //线程同步对象 88 SList<EventArgs*> *m_evtPending;//挂起的等待执行的事件 89 DWORD m_dwMainTrdID;//主线程ID 90 91 UINT_PTR m_timerID; //定时器ID,用来执行异步事件 92 93 SList<ISlotFunctor*> m_evtHandlerMap; 94 }; 95 }
在这个文件中提供了两个类,一个就是SNotifyCenter,另一个是TAutoEventMapReg<T>。
可以看到SNotifyCenter中除构造外只有4个public方法:
FireEventSync, FireEventAsync用来触发事件。
RegisterEventMap,UnregisterEventMap则用来提供事件处理订阅。
如何使用SNotifyCenter?
1、在main中实例化SNotifyCenter。(不明白可以参考demo)
2、定义需要通过通知中心分发的事件类型,首先定义事件,然后向通知中心注册,参见下面代码:
1 void CMainDlg::OnBtnStartNotifyThread() 2 { 3 if(IsRunning()) return; 4 SNotifyCenter::getSingleton().addEvent(EVENTID(EventThreadStart)); 5 SNotifyCenter::getSingleton().addEvent(EVENTID(EventThreadStop)); 6 SNotifyCenter::getSingleton().addEvent(EVENTID(EventThread)); 7 8 EventThreadStart evt(this); 9 SNotifyCenter::getSingleton().FireEventSync(&evt); 10 BeginThread(); 11 } 12 13 void CMainDlg::OnBtnStopNotifyThread() 14 { 15 if(!IsRunning()) return; 16 17 EndThread(); 18 EventThreadStop evt(this); 19 SNotifyCenter::getSingleton().FireEventSync(&evt); 20 21 SNotifyCenter::getSingleton().removeEvent(EventThreadStart::EventID); 22 SNotifyCenter::getSingleton().removeEvent(EventThreadStop::EventID); 23 SNotifyCenter::getSingleton().removeEvent(EventThread::EventID); 24 }
3、使需要处理通知中心分发的事件的对象从TAutoEventMapReg继承,实现事件的自动订阅(方便在事件映射表中统一处理事件),这一步是可选的,你也可以直接使用SOUI提供的事件订阅机制向通知中心订阅特定事件。
4、在事件映射表里处理事件(没有第3步时,则同样没有这一步)。
具体用法参见SOUI的demo。
转载于:https://www.cnblogs.com/setoutsoft/p/5642056.html
第三十四篇:在SOUI中使用异步通知相关推荐
- 三十四、深入Java中的泛型(上篇)
@Author:Runsen @Date:2019年10月22日 19:39:21 作者介绍:Runsen目前大三下学期,专业化学工程与工艺,大学沉迷日语,Python, Java和一系列数据分析软件 ...
- Android探索之旅(第十四篇)Android中实现炫酷效果的Demo(持续收录中......)
RangeSeekBar Android简单实现订单模块类APP的物流详情页 Android开发中阴影效果的实现 Android 炫酷多重水波纹 MultiWaveHeader 利用Spannable ...
- python open 相对路径_第十四篇:Python中文件读写
修修心养养性 处世不必邀功,无过便是功:与人不求感德,无怨便是德. 大纲 打开和关闭文件 读文件(文本文件和二进制文件) 写文件(文本文件和二进制文件) 打开和关闭文件 1.1打开文件 我们使用文件之 ...
- “约见”面试官系列之常见面试题第三十四篇之事件冒泡、事件捕获、事件代理(建议收藏)
对于事件的传播机制,Netscape Communicator采用的是事件捕获(event capture),IE9.Safari.Chrome.Opera和Firefox采用的是事件冒泡(event ...
- 第三十四篇-Palette(调色板)的使用
由于屏幕录制图片转换关系,不甚清晰,还是附上效果图 可以看出,上面文字和背景颜色确实会根据图片的变化而变化. 里面有3个组件,toolbar,textview,imageview,其中textview ...
- 第三十四章、PyQt中的输入部件:QComboBox组合框功能详解
专栏:Python基础教程目录 专栏:使用PyQt开发图形界面Python应用 专栏:PyQt入门学习 老猿Python博文目录 一.概述 Designer中输入工具部件中的Combo Box组合框与 ...
- 第三十四篇 源极跟随器
最简单的源极跟随器 推导Vs的过程: 输出阻抗 计算源极跟随器输出阻抗1/gm的方法是,假设栅极接地,给输出端加上一个信号,再来计算相应的源电流,对应的漏极电流 id=gmvgs=gmv: 所以rou ...
- Android 天气APP(三十四)语音搜索
上一篇:Android 天气APP(三十三)语音播报 语音搜索 前言 正文 一.权限配置 二.用户体验优化 三.配置语音识别听写 四.语音搜索 五.地图天气添加语音搜索功能 六.城市搜索添加语音搜索功 ...
- 回溯法采用的搜索策略_强化学习基础篇(三十四)基于模拟的搜索算法
强化学习基础篇(三十四)基于模拟的搜索算法 上一篇Dyna算法是基于真实经验数据和模拟经验数据来解决马尔科夫决策过程的问题.本篇将结合前向搜索和采样法,构建更加高效的搜索规划算法,即基于模拟的搜索算法 ...
最新文章
- 【面向对象编程】(2) 类属性的定义及使用;__repr__()方法
- PostgreSQL_row_number() over()_应用实例
- 《深入理解C++11:C++ 11新特性解析与应用》——2.4 宏__cplusplus
- 减肥登Cell封面上热搜:华东师大热疗探索新突破,这一波网友们想象力大开
- 还在担心工作被AI取代?不如掌握这门硬实力,抢占职场发展机遇
- 具有趣味性的c语言项目,一个有趣的小程序
- Java方法重载与方法重写
- clock()、time()、clock_gettime()和gettimeofday()函数的用法和区别
- 堆排序HeapSort
- Unity HDRP 光照贴图
- 2021-2027全球及中国工业物联网通信产品行业研究及十四五规划分析报告
- mint-ui引用iconfont图标
- mysql索引类型及方法介绍
- PRA10.3 平台 API 接口调用
- 看《Sicko》,有感
- Kubernetes、C语言小白变怪兽、C++ Primer Plus、TCP/IP网络编程、JavaScript高级程序设计
- MariaDB源码分析——CONNECT类
- 解决mac的的789 uio jkl m,.不能用的问题
- 微信小程序中自定义函数的学习使用
- CAD如何使插入的块为分解状态?CAD如何绘制五瓣花?
热门文章
- 人群运动--Scene-Independent Group Profiling in Crowd
- Linux/ubuntu 服务器开启6010端口-X11服务-ssh连接
- ClickHouse系列教程三:MergeTree引擎分析
- java中异常回收_理解Java垃圾回收
- mongorepository查询条件_MongoDB动态条件之分页查询
- [k8s] 第五章 Pod详解
- 计算机ui答辩,KGUT1027 班级UI设计第一阶段成长答辩开始啦
- class没有发布到tomcat_基于Tomcat的Websocket范例及permessage-deflate扩展特性的研究
- wallpaper怎么改后缀_腾讯微信视频号怎么引流?腾讯视频号引流有哪些方法?
- java severlet教程_javaweb-severlet