MFC用户界面线程初学小结
一、MFC的线程分类
不同于Win32 API不区分线程的类型,MFC中将线程分为两种类型:用户界面线程(users-interface threads)和辅助线程(即工作线程,worker threads)两种。用户界面线程用来处理需要用户输入、用户产生的事件和消息的响应,辅助线程用来处理完成不需要用户输入的任务。
参考网址:
https://msdn.microsoft.com/zh-cn/library/975t8ks0(v=vs.120).aspx
二、创建用户界面线程
1、创建一个继承于CWinThread的类
要使用宏定义DECLARE_DYNCREATE 和IMPLEMENT_DYNCREATE来实现这个新创建的类,并且至少需要重写以下两个函数:InitInstance()和ExitInstance()。
InitInstance()函数用于初始化这个用户界面线程,在这个函数中,可以创建对一个你所需要的话框。执行成功时返回非零值,否则返回0。
示例如下(本文所有示例使用VS2013):
BOOL CMyDlgThread::InitInstance()
{
// TODO: 在此执行任意逐线程初始化
CSonDlg* pSonDlg = new CSonDlg;//创建一个非模态窗口
if (NULL != pSonDlg)
{
m_pSonDlg = pSonDlg;
m_pSonDlg->Create(IDD_DIALOG1, NULL);
m_pSonDlg->SetWindowTextW(_T("Dialog in MyDlgThread."));
m_pSonDlg->ShowWindow(SW_SHOW);
m_pSonDlg->UpdateWindow();//马上刷新窗口
}
else
{
return FALSE;//结束线程
}
m_pMainWnd = NULL;//为主窗口赋值
return TRUE;
}
ExitInstance()函数会在退出线程或者InitInstance()函数执行失败时被调用,在这个函数中可以对自行创建的对象等进行清理,清理完后,需要调用基类中的该函数。线程终止时,如果CWinThread::m_bAutoDelete的值为TRUE,会自动删除创建的CWinThread对象,m_bAutoDelete默认值即为TRUE。
int CMyDlgThread::ExitInstance()
{
// TODO: 在此执行任意逐线程清理
if (NULL != m_pSonDlg)//删除创建的对象
{
m_pSonDlg->DestroyWindow();
m_pSonDlg = NULL;
}
return CWinThread::ExitInstance();//调用基类中的该函数
}
2、使用AfxBeginThread()函数创建用户界面线程
AfxBeginThread()函数有两种重载类型,一种只能创建辅助线程,另一种可以创建用户界面线程和辅助线程。使用的类型如下:
CWinThread* AfxBeginThread(
CRuntimeClass* pThreadClass,
int nPriority = THREAD_PRIORITY_NORMAL,
UINT nStackSize = 0,
DWORD dwCreateFlags = 0,
LPSECURITY_ATTRIBUTES lpSecurityAttrs = NULL
);
入参含义如下所示:
创建成功返回新线程对象的指针,失败返回NULL。
3、使用ResumeThread()函数调用用户界面线程
由于创建用户界面线程时使用了CREATE_SUSPENDED标志,因此需要使用ResumeThread()函数来调用创建的用户界面线程。
示例如下:
CWinThread* pThread = AfxBeginThread(RUNTIME_CLASS(CMyDlgThread), NULL, NULL, CREATE_SUSPENDED);
if (NULL != pThread)
{
pThread->ResumeThread();//调用线程
}
参考网址:
https://msdn.microsoft.com/zh-cn/library/b807sta6(v=vs.120).aspx
https://msdn.microsoft.com/zh-cn/library/s3w9x78e(v=vs.120).aspx
三、退出创建的用户界面线程
在用户界面线程中调用PostQuitMessage()函数即可,入参是线程的退出代码,0表示成功完成任务。
示例如下:
void CSonDlg::OnCancel()
{
// TODO: 在此添加专用代码和/或调用基类
PostQuitMessage(0);
}
参考网址:
https://msdn.microsoft.com/zh-cn/library/2s21xzfe(v=vs.120).aspx
四、创建用户界面线程时,传入指定参数
为创建的界面线程类添加成员变量,用来存储参数,如下所示:
class CMyDlgThread : public CWinThread
{
DECLARE_DYNCREATE(CMyDlgThread)
protected:
CMyDlgThread(); // 动态创建所使用的受保护的构造函数
virtual ~CMyDlgThread();
public:
virtual BOOL InitInstance();
virtual int ExitInstance();
private:
CSonDlg* m_pSonDlg;
public:
CString m_strTemp; //添加成员变量,存储传入参数
protected:
DECLARE_MESSAGE_MAP()
};
用户界面线程创建后,先为添加的成员变量赋值再调用该线程,如下所示:
CWinThread* pThread = AfxBeginThread(RUNTIME_CLASS(CMyDlgThread), NULL, NULL, CREATE_SUSPENDED);
if (NULL != pThread)
{
((CMyDlgThread*)pThread)->m_strTemp = _T("TestParam");//为传入参数赋值
pThread->ResumeThread();//调用线程
}
参考网址:
https://blog.csdn.net/sniper_bing/article/details/5002191