如何安详终止线程
副标题#e#
对付Worker线程,终止线程可以利用线程的退出码作为返回值从线程函数返回。
对付UI线程,因为有动静轮回,需要发送一个WM_QUIT动静到线程的动静行列,当线程吸收到WM_QUIT动静时退出动静轮回。因此,竣事线程可以在线程内部挪用SDK的PostQuitMessage函数,发送WM_QUIT动静。
PostQuitMessage函数的界说如下:
void PostQuitMessage(int nExitCode);
个中:
nExitCode:线程的退出码。
MFC还提供了AfxEndThread函数,Worker线程和UI线程都可以通过在线程内部挪用AfxEndThread函数竣事线程。
AfxEndThread函数的界说如下:
void AfxEndThread(UINT nExitCode, BOOL bDelete = TRUE);
个中:
nExitCode:线程的退出码。
在MFC的THRDCORE.CPP中,AfxEndThread函数的相关代码如下:
// THRDCORE.CPP
void AFXAPI AfxEndThread(UINT nExitCode, BOOL bDelete)
{
// remove current CWinThread object from memory
AFX_MODULE_THREAD_STATE* pState = AfxGetModuleThreadState();
CWinThread* pThread = pState->m_pCurrentWinThread;
if (pThread != NULL)
{
ASSERT_VALID(pThread);
ASSERT(pThread != AfxGetApp());
// cleanup OLE if required
if (pThread->m_lpfnOleTermOrFreeLib != NULL)
(*pThread->m_lpfnOleTermOrFreeLib)(TRUE, FALSE);
if (bDelete)
pThread->Delete();
pState->m_pCurrentWinThread = NULL;
}
// allow cleanup of any thread local objects
AfxTermThread();
// allow C-runtime to cleanup, and exit the thread
_endthreadex(nExitCode);
}
#p#副标题#e#
从MFC代码中可以看出,AfxEndThread函数通过挪用_endthreadex函数终止线程。另外,函数还举办释放线程的仓库、删除线程工具等事情。
假如在其它线程中终止该线程,必需回收线程通信的要领实现。个中一种简朴的要领是成立一个变量,让线程监督该变量,当该变量为某个值时,则终止线程。
(1)建设1个基于对话框的应用措施,名称为Demo。
(2)在IDD_DEMO_DIALOG对话框资源中添加控件,如表所示。
范例
ID
标题
Static
IDC_STATIC
数据:
Edit
IDC_DATA
Button
IDC_BEGIN_THREAD
启动线程
Button
IDC_END_THREAD
终止线程
(3)在文件中界说线程通报参数的数据布局,代码如下:
// DemoDlg.h
typedef struct THREAD_PARAM
{
HWND hWnd;
int nData;
BOOL bExit;
}_THREAD_PARAM;
(4)在CDemoDlg类中添加成员变量,代码如下:
// DemoDlg.h
protected:
CWinThread* m_pThread;
THREAD_PARAM m_ThreadParam;
(5)在CDemoDlg类的结构函数中初始化成员变量,代码如下:
// DemoDlg.cpp
CDemoDlg::CDemoDlg(CWnd* pParent /*=NULL*/)
: CDialog(CDemoDlg::IDD, pParent)
{
// ...
m_pThread = NULL;
m_ThreadParam.nData = 0;
}
(6)在CDemoDlg类的OnInitDialog函数中添加如下代码:
// DemoDlg.cpp
BOOL CDemoDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// …
SetDlgItemInt(IDC_DATA, m_nData);
return TRUE;
}
(7)在文件中界说线程动静,代码如下:
// DemoDlg.h
#define WM_THREADMSG WM_USER+1
(8)在文件中界说线程函数,代码如下:
// DemoDlg.h
UINT ThreadProc(LPVOID pParam);
// DemoDlg.cpp
UINT ThreadProc(LPVOID pParam)
{
//线程参数
THREAD_PARAM* pThreadParam = (THREAD_PARAM*)pParam;
while (!pThreadParam->bExit)
{
Sleep(100);
pThreadParam->nData++;
//向主线程窗口发送动静
::PostMessage(pThreadParam->hWnd, WM_THREADMSG, 0, 0);
}
return 0;
}
(9)在CDemoDlg类中别离为Button控件添加BN_CLICKED添加动静处理惩罚函数,代码如下:
// DemoDlg.cpp
void CDemoDlg::OnBeginThread()
{
if (m_pThread != NULL)
{
AfxMessageBox(_T("线程已经启动。"));
return;
}
m_ThreadParam.hWnd = m_hWnd;
m_ThreadParam.bExit = FALSE;
//启动线程,初始为挂起状态
m_pThread = AfxBeginThread(ThreadProc, &m_ThreadParam,
THREAD_PRIORITY_ABOVE_NORMAL, 0, CREATE_SUSPENDED);
//线程竣事时不自动删除
m_pThread->m_bAutoDelete = FALSE;
//规复线程运行
m_pThread->ResumeThread();
}
void CDemoDlg::OnEndThread()
{
if (m_pThread == NULL)
{
AfxMessageBox(_T("线程已经终止。"));
return;
}
m_ThreadParam.bExit = TRUE;
//期待线程竣事
::WaitForSingleObject(m_pThread->m_hThread, INFINITE);
delete m_pThread;
m_pThread = NULL;
}
(10)在CDemoDlg类中添加自界说动静处理惩罚函数,代码如下:
#p#分页标题#e#
// DemoDlg.h
afx_msg LRESULT OnMsgFunc();
// DemoDlg.cpp
BEGIN_MESSAGE_MAP(CDemoDlg, CDialog)
ON_MESSAGE(WM_THREADMSG, OnMsgFunc)
END_MESSAGE_MAP()
LRESULT CDemoDlg::OnMsgFunc()
{
SetDlgItemInt(IDC_DATA, m_ThreadParam.nData);
return 1;
}