在使用duilib库的时候,发现这个UI框架确实是小而美,它真的只是个UI框架,除了这个一无所有。也可能是用习惯了QT的缘故,理所当然的把它也认作如此了。
在界面开发中,一般主线程是用来刷新UI及响应来自用户对UI的操作的,因此主线程上不能跑一些重度耗时的操作,比如文件读取或者网络操作之类的。
一但这些操作在主线程执行,那么主线程就没有时间去响应用户对UI的操作,那么外部表现就是界面失去响应或者卡顿。为了解决这个问题,我们理所当然的旧想到了,
既然主线程不能干“重”活,那么我们去创建一个子线程去帮它把这些活干了不就好了。Bingo思路是对的,如果子线程默默的干活(子线程不使用主线程的资源)
这不会发生任何问题。但是子线程把活干完了是不是得通知一下主线程,那么问题就来了,子线程需要访问主线程的资源,然而主线程也需要访问自己的资源,
这就涉及到资源竞争了,下意识的我们又想到了加锁。加锁确实是个不错的主意,但是这个效率有点低下,有没有更优雅的方案呢?当然是有啦,这就要拉出windows的
消息系统了,windows系统的界面是基于消息驱动了,那么子线程只需要往主线程发送一条通知消息即可,这条消息系统会把它放进主线程的消息队列中,主线程的消息
循环会把这条消息分发到相应的处理函数,我们只要在为这条消息定制一个处理函数即可。原理讲完了,show code time了。
1.首先当然是定义一条消息,在windwos系统中,所有的消息都是一个整数
1
2
| //WM_USER 0x0400
#define WM_UPDATEUI (0x0400+50)
|
2.在主线程的消息循环中处理这条消息
1
2
3
4
5
6
7
8
9
| LRESULT CDuiFrameWnd::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
if (uMsg == WM_UPDATEUI)
{
//更新进度条
static_cast<CProgressUI*>(m_PaintManager.FindControl(_T("filepgs")))->SetValue((int)wParam);
}
return __super::HandleMessage(uMsg,wParam,lParam);
}
|
3.在子线程中发送消息
1
2
3
4
| void Protocol::ReportSendProgress(int percent)
{
::PostMessage((HWND)ui_hwnd_, WM_UPDATEUI, percent, NULL);
}
|