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

计算机等级考试
excel电子表格计算日期差工龄生日等
2009全国计算机等级考试新变化
计算机二级DELPHI技巧:DELPHI获取U盘盘符代码
计算机二级:DELPHI中指针和类TLIST结合
计算机二级:DELPHI中使用Tlist类的学习
计算机二级DELPHI技巧:DELPHI程序错误类型
计算机三级网络技术:网站被黑的10大原因
计算机二级DELPHI设置DBGridEh自动排序方法
计算机等级考试辅导:禁止MessageBox()弹出的对话框
计算机等级考试:Windows7Shell命令大汇总
把表空间从字典托管模式升级成本地托管模式
去掉系统快捷方式箭头的途径:修改注册表
计算机一级辅导:电脑连续死机是什么问题
C++编程:如何安全终止线程
做一个合格的软驱磁头清洁工
电脑光驱读盘差怎么办?
教你还原不小心被删除的文件资料
DELPHI辅导:打开与编辑数据表
delphi数据库引擎管理器
计算机二级C++辅导:回调函数用法

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


出处:互联网   整理: 软晨网(RuanChen.com)   发布: 2009-10-04   浏览: 565 ::
收藏到网摘: 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;

  }