当前位置: 首页 > 图文教程 > 认证考试 > 计算机等级考试 > C++编程:如何安全终止线程

计算机等级考试
全国计算机等级考试调整方案
2006年4月全国计算机等级考试二级C笔试答案
全国计算机等级考试二级C语言典型题解析
全国计算机等级考试二级C语言入门:数组
参加国家计算机等级考试该如何学习C语言
全国计算机等级考试C语言之深入理解C语言指针
计算机等级考试二级C语言之指针、数组和函数
2007年12月全国计算机职业技能考试安排
2008四月全国计算机等级考试将有重大调整
2007年9月全国计算机等级考试二级VB笔试试卷
2007年9月全国计算机等级考试二级C语言笔试试卷
2007年9月全国计算机等级考试三级网络技术笔试试卷
2007年9月全国计算机等级考试二级VFP笔试试卷
2007年9月全国计算机等级考试四级参考答案
2007年9月全国计算机等级考试二级java程序设计参考答案
2007年9月全国计算机等级考试access数据库程序设计参考答案
全国计算机等级考试考试大纲
计算机等级考试二级应试技巧
2009年度计算机应用能力考试的考试模块调整
Word软件文档结构图制作技巧

计算机等级考试 中的 C++编程:如何安全终止线程


出处:互联网   整理: 软晨网(RuanChen.com)   发布: 2009-10-04   浏览: 564 ::
收藏到网摘: n/a

  对于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;

  }