小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

如何安全終止MFC線程

 3D建模仿真 2014-02-13

如何安全終止MFC線程


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

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

提前終止一個線程也不難:在線程函數(shù)中調(diào)用AfxEndThread就是了,其中要傳入的參數(shù)就是返回代碼。這會停止線程的執(zhí)行,釋放線程棧,及與線程相關(guān)的DLL,并從內(nèi)存中刪除線程對象。AfxEndThread必須在線程函數(shù)內(nèi)調(diào)用,如果用戶希望從一個線程結(jié)束另一個線程,則需要在兩個線程間建立通信機制。 

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

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

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

對于Worker線程,終止線程可以使用線程的退出碼作為返回值從線程函數(shù)返回。
  對于UI線程,因為有消息循環(huán),需要發(fā)送一個WM_QUIT消息到線程的消息隊列,當線程接收到WM_QUIT消息時退出消息循環(huán)。因此,結(jié)束線程可以在線程內(nèi)部調(diào)用SDK的PostQuitMessage函數(shù),發(fā)送WM_QUIT消息。
  PostQuitMessage函數(shù)的定義如下:
  void PostQuitMessage(int nExitCode);
  其中:
  nExitCode:線程的退出碼。
  MFC還提供了AfxEndThread函數(shù),Worker線程和UI線程都可以通過在線程內(nèi)部調(diào)用AfxEndThread函數(shù)結(jié)束線程。
  AfxEndThread函數(shù)的定義如下:
  void AfxEndThread(UINT nExitCode, BOOL bDelete = TRUE);
  其中:
  nExitCode:線程的退出碼。
  在MFC的THRDCORE.CPP中,AfxEndThread函數(shù)的相關(guān)代碼如下:
  // 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函數(shù)通過調(diào)用_endthreadex函數(shù)終止線程。此外,函數(shù)還進行釋放線程的堆棧、刪除線程對象等工作。
  如果在其它線程中終止該線程,必須采用線程通信的方法實現(xiàn)。其中一種簡單的方法是建立一個變量,讓線程監(jiān)視該變量,當該變量為某個值時,則終止線程。
 ?。?)創(chuàng)建1個基于對話框的應用程序,名稱為Demo。
 ?。?)在IDD_DEMO_DIALOG對話框資源中添加控件,如表所示。
  類型
  ID
  標題
  Static
  IDC_STATIC
  數(shù)據(jù):
  Edit
  IDC_DATA  
  Button
  IDC_BEGIN_THREAD
  啟動線程
  Button
  IDC_END_THREAD
  終止線程

(3)在文件中定義線程傳遞參數(shù)的數(shù)據(jù)結(jié)構(gòu),代碼如下: 
  // DemoDlg.h
  typedef struct THREAD_PARAM
  {
  HWND hWnd;
  int nData;
  BOOL bExit;
  }_THREAD_PARAM;
 ?。?)在CDemoDlg類中添加成員變量,代碼如下:
  // DemoDlg.h
  protected:
  CWinThread* m_pThread;
  THREAD_PARAM m_ThreadParam;
 ?。?)在CDemoDlg類的構(gòu)造函數(shù)中初始化成員變量,代碼如下:
  // DemoDlg.cpp
  CDemoDlg::CDemoDlg(CWnd* pParent /*=NULL*/)
  : CDialog(CDemoDlg::IDD, pParent)
  {
  // ...
  m_pThread = NULL;
  m_ThreadParam.nData = 0;
  }
 ?。?)在CDemoDlg類的OnInitDialog函數(shù)中添加如下代碼:
  // DemoDlg.cpp  
   BOOL CDemoDlg::OnInitDialog()
  {
  CDialog::OnInitDialog();
  // …
  SetDlgItemInt(IDC_DATA, m_nData);
  return TRUE;
  }
  (7)在文件中定義線程消息,代碼如下:
  // DemoDlg.h
  #define WM_THREADMSG WM_USER+1
 ?。?)在文件中定義線程函數(shù),代碼如下:
  // DemoDlg.h
  UINT ThreadProc(LPVOID pParam);
  // DemoDlg.cpp
  UINT ThreadProc(LPVOID pParam)
  {
  //線程參數(shù)
  THREAD_PARAM* pThreadParam = (THREAD_PARAM*)pParam;
  while (!pThreadParam->bExit)
  {
  Sleep(100);
  pThreadParam->nData++;
  //向主線程窗口發(fā)送消息
  ::PostMessage(pThreadParam->hWnd, WM_THREADMSG, 0, 0);
  }
  return 0;
  }
 ?。?)在CDemoDlg類中分別為Button控件添加BN_CLICKED添加消息處理函數(shù),代碼如下:
  // DemoDlg.cpp
  void CDemoDlg::OnBeginThread()
  {
  if (m_pThread != NULL)
  {
  AfxMessageBox(_T("線程已經(jīng)啟動。"));
  return;
  }
  m_ThreadParam.hWnd = m_hWnd;
  m_ThreadParam.bExit = FALSE;
  //啟動線程,初始為掛起狀態(tài)
  m_pThread = AfxBeginThread(ThreadProc, &m_ThreadParam,
  THREAD_PRIORITY_ABOVE_NORMAL, 0, CREATE_SUSPENDED);
  //線程結(jié)束時不自動刪除
  m_pThread->m_bAutoDelete = FALSE;
  //恢復線程運行
  m_pThread->ResumeThread();
  }
  void CDemoDlg::OnEndThread()
  {
  if (m_pThread == NULL)
  {
  AfxMessageBox(_T("線程已經(jīng)終止。"));
  return;
  }
  m_ThreadParam.bExit = TRUE;
  //等待線程結(jié)束
  ::WaitForSingleObject(m_pThread->m_hThread, INFINITE);
  delete m_pThread;
  m_pThread = NULL;
  }
 ?。?0)在CDemoDlg類中添加自定義消息處理函數(shù),代碼如下:
  // 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;  
   }

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多