程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> 關於C++ >> 如何安全終止線程

如何安全終止線程

編輯:關於C++

對於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);
}

從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類中添加自定義消息處理函數,代碼如下:

// 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;
}

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved