如何结束线程?

时间:2022-11-17 22:40:35

如何从其他线程结束下面这个线程?   
   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)处。   



(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;   
   }   
    
    
   总之,没有办法能让线程“正常地立刻”结束,   
   您应该等待它结束。   
    
    



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



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



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



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



用TerminateThread()函数



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



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;   
   }



看来是没有好的方法。   
    
   期望找到一下类似于下面这样的实现方法:   
   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;   
   }



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



最安全的办法是线程的循环体里面检查一个退出事件,此事件一触发就自己清除资源并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;       
   }       



问题是在xxx_func处阻塞了啊



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



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



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;



  
   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();   
   }   



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