CSDN首页 空间 新闻 论坛 Blog 下载 读书 网摘 搜索 .NET Java 视频 接项目 求职 在线学习 买书 程序员 通知
不看会后悔的Windows XP之经验谈 简单快捷DIY实用家庭影院
CSDN社区
搜索 收藏 打印 关闭
CSDN社区 >  VC/MFC >  进程/线程/DLL

如何结束线程?

楼主Kernel_Don()2005-01-06 23:22:37 在 VC/MFC / 进程/线程/DLL 提问

如何从其他线程结束下面这个线程?  
  DWORD   WINAPI   ThreadProc(LPVOID   param)  
  {  
          while   (b   ==   TRUE)  
          {  
                  xxx_func(...);  
          }  
   
          return   0;  
  }  
  本来我是用TerminateThread来结束这个线程的,但由于TerminateThread太粗暴,没有释放线程资源,从任务管理器中看到有内存泄漏。  
  一般地,当需要结束该线程时,设置b=FALSE即可使线程运行到while(条件)时结束循环,从而正常结束线程。但问题是由于xxx_func是一个阻塞的函数(比如accept、WaitForCommEvent等函数),所以通常这个线程停止在xxx_func处等待,运行不到while(b==TRUE)处。  
  问题点数:100、回复次数:18Top

1 楼iicup(双杯献酒)回复于 2005-01-06 23:52:21 得分 10

(1)不要用  
  while(b   ==   TRUE)  
  应该用  
  while(b)  
   
  (2)既然您已经能通过b来控制ThreadProc  
  您的主要问题是:  
   
  xxx_func是一个阻塞的函数  
   
  因此,解决方法是:  
  让xxx_func每次只阻塞很短的时间。  
   
  (3)如果结束线程的行为发生在进程即将结束,  
  那么,您可以  
  <1>通过CreateThread返回的HANDLE来判断线程是否结束,  
        在线程结束后,主线程再结束。  
  <2>通过在ThreadProc内的另外一变量来判断线程是否结束。  
  比如  
   
  BOOL   bThreadRun   =   FALSE;   //   线程正在运行的标志  
  DWORD   WINAPI   ThreadProc(LPVOID   param)  
  {  
          bThreadRun   =   TRUE;  
          while   (b   ==   TRUE)  
          {  
                  xxx_func(...);  
          }  
   
          bThreadRun   =   FALSE;  
          return   0;  
  }  
   
   
  总之,没有办法能让线程“正常地立刻”结束,  
  您应该等待它结束。  
   
   
  Top

2 楼EnochShen(小疯子:真的好菜—知耻而后勇!)回复于 2005-01-07 00:01:56 得分 5

在xxx_func里面可以使用WaitForMultipleObjects,用一个全局的HANDLE来控制xxx_func的结束Top

3 楼Kernel_Don()回复于 2005-01-07 00:07:28 得分 0

我是想寻找一个让线程"正常地立刻结束"的方法,或没有内存泄漏的"不那么正常立刻结束"的方法也可。  
  把xxx_func设成每次等待很短时间不好设啊。它可能等待几微秒,也可能等待几秒,也可能几个小时,说不定的。  
  结束线程的行为不是发生在进程即将结束,而且是可能结束了后又要再次生成新的线程,这样才有内存泄漏的问题啊,如果结束线程的行为发生在进程即将结束,那用TerminateThread也无所谓了,泄漏的内存由系统也可回收。Top

4 楼Kernel_Don()回复于 2005-01-07 00:09:17 得分 0

xxx_func是accept、WaitForCommEvent之类的系统函数,不是我自已写的函数。Top

5 楼bachelor2001(无中生有)回复于 2005-01-07 11:30:45 得分 10

设一个线程是否要退出的标志,阻塞函数不应无限至阻塞,应该设一个等待时间循环判断,等待的时间设短一点比如几十毫秒,这样在每次等待后判断线程退出标志  
  退出标志应定义为   volatileTop

6 楼xuzheng318(忧郁王子)回复于 2005-01-07 11:39:33 得分 5

用TerminateThread()函数Top

7 楼bachelor2001(无中生有)回复于 2005-01-07 11:44:11 得分 10

由主线程将退出标志设为"要退出",退出标志应该是全局变量,且应加"volatile"定义,这样就保证子线程和主线程读取和设置的是同一个变量  
  主线程退出前先设置该标志,然后等待一段时间让子线程退出,一段时间后若子线程仍未退出,则只能Terminate了Top

8 楼crystal521(【云淡风轻】)回复于 2005-01-07 11:48:45 得分 10

1、使用TerminateThread()  
  2、使用全局变量  
  bool   bExit;  
  void   CTestView::OnButton1()       //启动线程    
  {  
                    bExit   =   false;  
  FThread=CreateThread(NULL,0,thx,  
  (LPVOID   )&x,CREATE_SUSPENDED,&dwThreadID);  
   
  ResumeThread(FThread);  
  }  
  DWORD   WINAPI   thx(LPVOID   param)  
  {  
  while(TRUE)  
  {  
      //...  
  }  
  if(bExit)  
  ExitThread(0);  
   
  }  
  return   0;  
  }  
  void   CTestView::OnButton2()   //终止线程  
  {  
  bExit   =   true;  
  }Top

9 楼Kernel_Don()回复于 2005-01-07 12:31:57 得分 0

看来是没有好的方法。  
   
  期望找到一下类似于下面这样的实现方法:  
  void   CTestView::OnButton1()       //启动线程    
  {  
  hThread=CreateThread(NULL,0,thx,(LPVOID   )&x,0,&dwThreadID);  
  }  
  DWORD   WINAPI   thx(LPVOID   param)  
  {  
  while(TRUE)  
  {  
          try  
                            {  
                                    xxx_func(...);  
                            }  
                            catch   (...)  
                            {  
                                    ExitThread(0);  
                            }  
  }  
  return   0;  
  }  
  void   CTestView::OnButton2()   //终止线程  
  {  
  throw   exception   to   pThread;  
  }Top

10 楼sanhechen(cchun)回复于 2005-01-07 12:34:32 得分 0

我想发帖子,怎么发不了啊?  
  Top

11 楼crystal521(【云淡风轻】)回复于 2005-01-07 12:43:40 得分 10

最安全的办法是线程的循环体里面检查一个退出事件,此事件一触发就自己清除资源并return。      
  要通知此线程退出的模块就PostThreadMessage函数,将退出事件post给该线程。      
     
  hEventFinish         =         CreateEvent(NULL,TRUE,FALSE,NULL);//创建手工重置的Event对象          
     
  DWORD     WINAPI     DisplayData(LPVOID     param)      
  {      
                        while(TRUE)      
                        {      
                                        if(     WaitForSingleObject(pDlg->hEventFinish,0)         ==         WAIT_OBJECT_0)              
                                                        return         0;                                                                         //让线程函数正常返回      
     
                             
                        //...DisplayData      
     
                             
                        }      
                        return     0;      
  }      
  Top

12 楼Kernel_Don()回复于 2005-01-07 12:59:28 得分 0

问题是在xxx_func处阻塞了啊Top

13 楼bachelor2001(无中生有)回复于 2005-01-07 14:07:17 得分 0

如果是一定要阻塞,且是无限制时间的,那就没有办法了.比如你的主线程阻塞了,而你却非要它自己退出来,这可能吗?Top

14 楼bachelor2001(无中生有)回复于 2005-01-07 14:11:11 得分 10

不知你是否可以用MsgWaitForMultipleObjects,这样检测到一定的事件发生也可以退出阻塞等待Top

15 楼zhangqu_980371(能坚持一辈子的东西太少)回复于 2005-01-07 15:52:10 得分 5

if   (!this->m_hThread)  
  return   FALSE;  
   
  TRACE(_T("Killing   thread   %x   ...\n"),   m_hThreadId);  
   
  //   reset   the   m_hEventKill   which   signals   the   thread   to   shutdown  
  VERIFY(::SetEvent(this->m_hEventKill));  
   
  //   allow   thread   to   run   at   higher   priority   during   kill   process  
  if   (::WaitForSingleObject(this->m_hThread,   m_dwKillingWait)   ==   WAIT_TIMEOUT)  
  ::TerminateThread(this->m_hThread,   0);  
   
  TRACE(_T("Thread   %x   killed\n"),   m_hThreadId);  
   
  ::ResetEvent(this->m_hEventKill);  
   
  m_bActive   =   FALSE;  
   
  return   TRUE;Top

16 楼chenjunge(狄克)回复于 2005-01-07 16:43:01 得分 10

 
  DWORD   WINAPI   Check(LPVOID   lpParameter   )     //   thread   data  
  {  
  //DebugBreak();  
  COoDlg   *pMonitor   =   (COoDlg*)lpParameter;  
  while(pMonitor->bStart)  
  {  
  OVERLAPPED   opd;  
  if(NotifyAddrChange(NULL,&opd)   ==   NO_ERROR)  
  {  
  TRACE("aaa");  
  }  
  WaitForSingleObject(pMonitor->m_hThread,5000);  
  }  
  return   FALSE;  
  }  
  void   COoDlg::OnOK()    
  {  
  DWORD   ThreadID;      
  m_hThread   =   CreateThread(NULL,0,Check,this,0,&ThreadID);  
  if(m_hThread   ==   NULL)  
  {  
  //AfxMessageBox("创建监控线程失败!");  
  return   ;//FALSE;  
  }  
  else  
  {  
  bStart   =   true;  
  return   ;//TRUE;  
  }  
  return   ;//FALSE;  
   
  }  
   
  void   COoDlg::OnCancel()    
  {  
  bStart=0;  
  if(m_hThread)  
  {  
  if(::WaitForSingleObject(m_hThread,1000)   ==   WAIT_TIMEOUT)  
  {  
  //如果超时:  
  TerminateThread(m_hThread,NULL);  
  }  
  CloseHandle(m_hThread);  
  m_hThread   =   NULL;  
  }  
  //CDialog::OnCancel();  
  }  
  Top

17 楼oyljerry(【勇敢的心】→ ㊣提拉米苏√㊣)回复于 2005-01-09 16:31:42 得分 5

阻塞处应该总有一个超时什么的吧,可以用WaitForSingleObject设置一下超时返回,这样就可以跳出阻塞了Top

18 楼blastzgd(悟道)回复于 2005-01-10 16:56:17 得分 10

CancelBlockingCallTop

相关问题

  • 线程如何结束
  • 线程如何结束?
  • 线程问题:我如何知道线程已经结束了?
  • 如何结束一个线程?
  • 如何结束一个线程
  • 如何结束一个线程?
  • 在MFC中如何结束UI线程?
  • 如何结束当前的线程
  • 如何强制结束一个线程?
  • VC中如何结束一个线程?

关键词

  • 线程
  • 函数
  • 内存泄漏
  • 结束
  • 退出
  • 阻塞
  • terminatethread
  • bexit
  • bthreadrun
  • heventkill

得分解答快速导航

  • 帖主:Kernel_Don
  • iicup
  • EnochShen
  • bachelor2001
  • xuzheng318
  • bachelor2001
  • crystal521
  • crystal521
  • bachelor2001
  • zhangqu_980371
  • chenjunge
  • oyljerry
  • blastzgd

相关链接

  • Visual C++类图书
  • Visual C++类源码下载

广告也精彩

反馈

请通过下述方式给我们反馈
反馈
提问
网站简介|广告服务|VIP资费标准|银行汇款帐号|网站地图|帮助|联系方式|诚聘英才|English|问题报告
北京创新乐知广告有限公司 版权所有, 京 ICP 证 070598 号
世纪乐知(北京)网络技术有限公司 提供技术支持
Copyright © 2000-2008, CSDN.NET, All Rights Reserved
GongshangLogo