第三十四篇:在SOUI中使用异步通知
2016-07-04 23:27
423 查看
概述
异步通知是客户端开发中常见的需求,比如在一个网络处理线程中要通知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。
相关文章推荐
- Android系统应用---SystemUI之二:Statusbar显示流程以及系统状态图标更新分析
- 微软极品工具箱-Sysinternals Suite
- UIScrollView增加刷新
- CDMA系统的UIM卡介绍 ,IMSI,ESN,MDN
- 消息队列(Message Queue)简介及其使用
- uuid_short() 源代码
- Android酷炫实用的开源框架(UI框架)
- 非GUI-Qt程序运行后显示Console(简单好用)
- deque 迭代器失效的问题详解
- The current branch is not configured for pull No value for key branch.master.merge found in configur
- NSOperationQueue队列
- hbase KeyValue结构打印
- Vue.js学习资料集(持续更新中)
- block自定义UIButton
- VM虚拟机----安装虚拟机时出现failed to create the requested registry key
- UIPopoverController
- TOJ 1765. Longest Ordered Subsequence
- java 获取request参数集
- 使用UISearchController的时候 cellForRow 崩溃
- 百度富文本编辑器UEDITOR