工作者线程一般适合后台处理,没有消息队列,看不见、感觉不到它。
现在做一个让人能看得见、感觉得到的工作者线程。
基于对话框,工程名:241
启动按钮:IDC_START_WORKER
暂停按钮:IDC_PAUSE
继续按钮:IDC_CONTINUE
进度条: IDC_PROGRESS 关联变量:m_ctrlProgress
自定义 消息: WM_MSG_WORKER 及其响应函数: OnWorkerMessage()
点击“启动按钮”,程序创建一个线程,线程执行函数为 WorkerThread(),它每隔0.1秒,发送自定义的 WM_MSG_WORKER 消息到主窗口。
响应函数则会根据消息的附加值,让进度条进度不断增加,当进度条满格后,关闭线程。
这样,工作者线程在后台看不见的处理,通过进度条的滚动,变得看得见。
添加代码,如下:
1、在 CMy241Dlg.h中 自定义消息 :#define WM_MSG_WORKER WM_USER+1
2、在 CMy241Dlg.h中
class CMy241Dlg : public CDialog
{
public:
CWinThread *m_pWorkThread; // 定义线程指针
LRESULT OnWorkerMessage(WPARAM wParam,LPARAM lParam); // 声明消息响应函数
3、在 CMy241Dlg.cpp 中,消息映射 BEGIN_MESSAGE_MAP(CMy241Dlg, CDialog)
......
//}}AFX_MSG_MAP
ON_MESSAGE(WM_MSG_WORKER,OnWorkerMessage)
END_MESSAGE_MAP()
消息响应函数的具体实现:
LRESULT CMy241Dlg::OnWorkerMessage(WPARAM wParam,LPARAM lParam)
{
m_ctrlProgress.SetPos(wParam);
if (wParam==100) // 如果进度条已满
{
DWORD code;
GetExitCodeThread(m_pWorkThread->m_hThread,&code);
if (code==STILL_ACTIVE)
{
TerminateThread(m_pWorkThread->m_hThread,-1); // 终止线程
}
delete m_pWorkThread;
m_pWorkThread=NULL;
GetDlgItem(IDC_START_WORKER)->SetWindowText("启动WORKER线程");
}
return 0;
}
4、初始化进度条:
BOOL CMy241Dlg::OnInitDialog()
{
CDialog::OnInitDialog();
..........
m_ctrlProgress.SetRange(0,100);
m_ctrlProgress.SetPos(1);
return TRUE; // return TRUE unless you set the focus to a control
}
5、为启动按钮添加 BN_CLICKED 事件处理函数:
void CMy241Dlg::OnStartWorker()
{
// TODO: Add your control notification handler code here
if (m_pWorkThread==NULL) // 如果线程不存在
{
// 创建工作者线程:WorkerThrea,
// 传递的参数是当前窗口的句柄:GetSafeHwnd()
// 线程的初始状态:挂起 CREATE_SUSPENDED
m_pWorkThread= AfxBeginThread(WorkerThread,GetSafeHwnd(),0,0,CREATE_SUSPENDED,0);m_pWorkThread->m_bAutoDelete=FALSE;
m_pWorkThread->ResumeThread(); // 执行线程
GetDlgItem(IDC_START_WORKER)->SetWindowText("停止WORKER线程");
}
else // 如果线程已存在
{
DWORD code;
GetExitCodeThread(m_pWorkThread->m_hThread,&code);
if (code==STILL_ACTIVE) // 仍在运行中
{
TerminateThread(m_pWorkThread->m_hThread,-1); // 停止线程
}
delete m_pWorkThread;
m_pWorkThread=NULL;
GetDlgItem(IDC_START_WORKER)->SetWindowText("启动WORKER线程");
}
}
6、 线程执行函数:
UINT WorkerThread(LPVOID lParam)
{
HWND hWnd=(HWND)lParam; // 创建线程时,传递的参数是窗口句柄,所以用(HWND)强制转换为句柄
for (int i=0;i<=100;i++)
{
Sleep(100); // 间隔100 毫秒
SendMessage(hWnd,WM_MSG_WORKER , i ,0); // 把自定义消息WM_MSG_WORKER 发送给主窗口,附加消息 i
}
return 0;
}
7、暂停按钮:IDC_PAUSE 的 BN_CLICKED 事件处理函数:
void CMy241Dlg::OnPause()
{
// TODO: Add your control notification handler code here
SuspendThread(m_pWorkThread->m_hThread);
}
8、继续按钮:IDC_CONTINUE 的 BN_CLICKED 事件处理函数:
void CMy241Dlg::OnContinue()
{
// TODO: Add your control notification handler code here
ResumeThread(m_pWorkThread->m_hThread);
}