日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

安全终止MFC线程全

發布時間:2023/12/18 编程问答 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 安全终止MFC线程全 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

終止線程?
有兩種情況可以使線程結束:控制函數結束或者根本就不允許線程完成,而提前終止它。我們可以想象在WORD中進行后臺打印,如果打印結束了,那線程就可以結束了。如果用戶中止了打印,那后臺打印線程也要終止了。本文將主要介紹對這兩種情況的實現,并且介紹如何獲得線程的結束代碼。?

1.對于工作線程,結束它是比較容易的:退出線程函數然后返回一個結束原因的代碼就是了。用戶可以使用AfxEndThread函數或直接利用return返回。通常0代表成功返回,這不是硬性規定,一切要取決于你了。對于用戶界面線程,調用::PostQuitMessage,它所要的唯一的參數就是返回代碼,也就是工作線程中的那個碼,性質是一樣的。0通常代表成功。?

2.提前終止一個線程也不難:在線程函數中調用AfxEndThread就是了,其中要傳入的參數就是返回代碼。這會停止線程的執行,釋放線程棧,及與線程相關的DLL,并從內存中刪除線程對象。AfxEndThread必須在線程函數內調用,如果用戶希望從一個線程結束另一個線程,則需要在兩個線程間建立通信機制。?

如果需要獲得線程返回代碼,只需要調用::GetExitCodeThread就可以了。這個函數的具體作用就看大家具體去查幫助了。它傳入的是線程的句柄,和一個提向返回代碼的指針。將來就從那個指針得到返回代碼。如果線程仍然處于活動狀態,那么::GetExitCodeThread得到的返回代碼為STILL_ACTIVE,如果已經退出則得到的是返回代碼的地址。獲得CWinThread對象的返回代碼還需要一點麻煩,通常,當CWinThread線程結束時,線程對象就刪除了,因為這個對象不存在了,也就沒有辦法訪問對象的m_hThread變量了,為了避免這種情況,可以有兩種方法:?

將m_bAutoDelete設置為FALSE,這使得線程結束后CWinThread對象仍然存在,這樣用戶就可以訪問m_hThread了,但是如果用戶使用這種方法,用戶需要自己析構CWinThread對象。這種方法是推薦的方法。?

下一個方法是另外保存線程的句柄。在線程創建后,將m_hThread保存在另一個變量中,以后訪問這個變量就是了。但是要小心,在復制句柄以前線程并沒有結束,最安全的方法是在AfxBeginThread中傳入CREATE_SUSPENDED,保存句柄,然后通過調用ResumeThread,重新開始線程。這兩種方法都可以幫助用戶得到CWinThread對象的返回代碼。

對于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 memoryAFX_MODULE_THREAD_STATE* pState = AfxGetModuleThreadState();CWinThread* pThread = pState->m_pCurrentWinThread;if (pThread != NULL){ASSERT_VALID(pThread);ASSERT(pThread != AfxGetApp());// cleanup OLE if requiredif (pThread->m_lpfnOleTermOrFreeLib != NULL)(*pThread->m_lpfnOleTermOrFreeLib)(TRUE, FALSE);if (bDelete)pThread->Delete();pState->m_pCurrentWinThread = NULL;}// allow cleanup of any thread local objectsAfxTermThread();// allow C-runtime to cleanup, and exit the thread_endthreadex(nExitCode); }

從MFC代碼中可以看出,AfxEndThread函數通過調用_endthreadex函數終止線程。此外,函數還進行釋放線程的堆棧、刪除線程對象等工作。

如果在其它線程中終止該線程,必須采用線程通信的方法實現。其中一種簡單的方法是建立一個變量,讓線程監視該變量,當該變量為某個值時,則終止線程。

(1)創建1個基于對話框的應用程序,名稱為Demo。

(2)在IDD_DEMO_DIALOG對話框資源中添加控件,如表所示。

類型ID標題
StaticIDC_STATIC數據:
EditIDC_DATA?
ButtonIDC_BEGIN_THREAD啟動線程
ButtonIDC_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;   }

總結

以上是生活随笔為你收集整理的安全终止MFC线程全的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。