工作线程分离并不是通常意义上的多线程,其实并不难学。多线程一般指并发多工作线程,一般需要进行各种同步操作以避免意外发生,但是分离工作线程并不需要。
分离工作线程的好处是可以做耗时的阻塞式操作(如多媒体处理、网络和磁盘操作等),同时保证界面不会无响应。
最简单的方法是使用AfxBeginThread运行工作线程,在工作线程中SendMessage、PostMessage向主线程报告状态。
CWinThread * AfxBeginThread(pfnThreadProc, pParam[, nPriority, nStackSize, dwCreateFlags, lpSecurityAttrs]);
这里一般只需要前两个参数
第一个参数
pfnThreadProc是线程入口点函数
UINT ThreadProc(LPVOID pParam),必须是全局函数或静态函数
第二个参数
pParam是一个自定义指针(LPVOID),允许你传递一个指针(可以是一个自定义结构或CWnd*等其它指针)
注意工作线程内不要直接对MFC中的界面类进行操作,即不要直接更新界面,以防止出问题。
LRESULT pWnd->
SendMessage(
uMsg,
wParam,
lParam);
BOOL pWnd->
PostMessage(
uMsg,
wParam,
lParam);
这两个函数允许向主线程发送消息,用来通知主线程更新界面。其中SendMessage会直接调用主线程的消息处理函数(同步调用),而PostMessage只是发送一个消息让消息循环处理(异步调用)。同步调用适合
调用需要数据完整性的过程,而异步调用适合
调用不需要数据完整性的过程,或者
通知线程退出。
这里发送的不一定要是自定义消息,一个偷懒的方法可以发送一个
WM_TIMER,第二个参数
wParam就是OnTimer中的
nIDEvent,同样可以实现通知主线程更新UI的效果。
UINT ThreadProc1(LPVOID pParam)
{
CWorkThreadDlg *pWnd = (CWorkThreadDlg*)pParam; // 获取窗口指针
while(pWnd->m_progint < 100) {
pWnd->m_progint++; // 工作
pWnd->SendMessage(WM_TIMER, 1, 0); // 报告工作(同步)
Sleep(50); // 延时
}
pWnd->PostMessage(WM_TIMER, 2, 0); // 报告处理完成(异步)
return 0;
}
void CWorkThreadDlg::OnBnClickedStart()
{
AfxBeginThread(ThreadProc1, this); // 第二个参数是自定义指针,这里传递窗口指针
}
void CWorkThreadDlg::OnBnClickedReset()
{
m_progint = 0;
m_progress.SetPos(m_progint);
}
void CWorkThreadDlg::OnTimer(UINT_PTR nIDEvent)
{
if (nIDEvent == 1) { // 接到报告工作
m_progress.SetPos(m_progint);
}
else if (nIDEvent == 2) { // 接到报告完成
AfxMessageBox("工作完成!");
}
}
WorkThread.rar
1.04MB
RAR
52次下载