-
Notifications
You must be signed in to change notification settings - Fork 283
第三十四篇:在SOUI中使用异步通知
原文链接:《第三十四篇:在SOUI中使用异步通知》
异步通知是客户端开发中常见的需求,比如在一个网络处理线程中要通知UI线程更新等等。
通常在Windows编程中,为了方便,我们一般会向UI线程的窗口句柄Post/Send
一个窗口消息从而达到将非UI线程的事件切换到UI线程处理的目的。
在SOUI引入通知中心以前要在SOUI中处理非UI线程事件我也推荐用上面的方法。
使用窗口消息至少有以下两个不足:
-
需要在线程中持有一个窗口句柄。
-
发出的消息只能在该窗口句柄的消息处理函数里处理。
最新的SOUI引入了一个新的单例对象:SNotifyCenter
,专门用来处理这类问题。
新的SNotifyCenter解决了窗口消息存在的上面的两个问题:
-
通过使用全局单例,
SNotifyCenter
可以在代码任意位置获取它的指针(前提当然是要在它的生命周期内); -
使用
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
则用来提供事件处理订阅。
-
在main中实例化
SNotifyCenter
。(不明白可以参考demo) -
定义需要通过通知中心分发的事件类型,首先定义事件,然后向通知中心注册,参见下面代码:
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);
}
-
使需要处理通知中心分发的事件的对象从TAutoEventMapReg继承,实现事件的自动订阅(方便在事件映射表中统一处理事件),这一步是可选的,你也可以直接使用SOUI提供的事件订阅机制向通知中心订阅特定事件。
-
在事件映射表里处理事件(没有第3步时,则同样没有这一步)。
具体用法参见SOUI的demo。
UI? just so so!
- 第一篇:SOUI是什么?
- 第二篇:SOUI源码的获取及编译
- 第三篇:用SOUI能做什么?
- 第四篇:SOUI资源文件组织
- 第五篇:在SOUI中使用XML布局属性指引
- 第六篇:在SOUI中用九宫格拉伸方式显示一个图片资源
- 第七篇:创建一个SOUI的Hello World
- 第八篇:SOUI中控件事件的响应
- 第九篇:在SOUI中使用多语言翻译
- 第十篇:扩展SOUI的控件及绘图对象
- 第十一篇:SOUI系统资源管理
- 第十二篇:SOUI的utilities模块为什么要用DLL编译?
- 第十三篇:在SOUI中使用有窗口句柄的子窗口
- 第十四篇:在SOUI中使用定时器
- 第十五篇:在SOUI中消息通讯
- 第十六篇:SWindow的布局属性pos2type及offset
- 第十七篇:使用窗口的cache属性加速SOUI的渲染
- 第十八篇:在SOUI中实现PreTranslateMessage
- 第十九篇:提高SOUI应用程序渲染性能的三种武器
- 第二十篇:在SOUI中使用分层窗口
- 第二十一篇:SOUI中的控件注册机制
- 第二十二篇:在SOUI中使用代码向窗口中插入子窗口
- 第二十三篇:在SOUI中使用LUA脚本开发界面
- 第二十四篇:导出SOUI对象到LUA脚本
- 第二十五篇:在SOUI中做事件分发处理
- 第二十六篇:两个SOUI新控件 ---- SListView和SComboView
- 第二十七篇:SOUI中控件属性查询方法
- 第二十八篇:SOUI中自定义控件开发过程
- 第二十九篇:使用SOUI的SMCListView控件
- 第三十篇:SOUI模块结构图及SOUI框架图
- 第三十一篇:SOUI布局之相对于特定兄弟窗口
- 第三十二篇:在SOUI2.0中像android一样使用资源
- 第三十三篇:使用uiresImporter生成uires.idx及skin.xml
- 第三十四篇:在SOUI中使用异步通知
﹊﹊﹊﹊﹊﹊﹊﹊﹊﹊
This wiki is created by [SOUI Team]