Ⅰ c++关闭线程函数
退出线程可以有四种方法:
1.线程函数的return返回(最好这样):
其中用线程函数的return返回, 而终止线程是最安全的, 在线程函数return返回后, 会清理函数内申请的类对象, 即调用这些对象的析构函数. 然后会自动调用 _endthreadex()函数来清理 _beginthreadex(...)函数申请的资源(主要是创建的tiddata对象).
2.调用 _endthreadex()函数 或 ExitThread()函数(最好不要):
如果使用这两种方法退出线程, 则不会执行线程函数的return语句, 所以就不会调用线程函数作用域内申请的类对象的析构函数, 会造成内存泄露.
剩下两种是在程序设计中一定要避免的.
3.用同一个进程中的另一个线程调用 TerminateThread()函数(必须避免);
4.终止该线程所在的进程(绝对避免);
但是要说_endthreadex完全没有用肯定是不对的,_endthreadex并不是一个过时的函数,正确的使用并不会带来问题。
比如在线程的主函数中,return是_endthreadex的一个良好替代,就像main函数里面return是exit()或ExitProccess()的良好替代一样,但是这不表示exit函数没用。比如线程调用了一个子函数,如果子函数决定退出线程,return是没用的,_endthreadex即可终结线程。
但是这个设计不好,因为可能造成LZ提出的资源泄漏。尤其考虑到后台线程终结后的资源泄漏比主线程的资源泄漏更要命(主线程退出后,进程就退出了,OS会清理一切资源,无所谓泄露不泄露,而子线程退出后主线程可能还会运行很久,并且可能有大量的同类型的子线程退出,会造成要命的泄露)
良好的设计还是返回线程的主函数,让threadproc来决定是不是要退出,从这个意义上说,_endthreadex没有必要。微软也指出,有些程序员就是要调用exit系列函数(ExitThread,ExitProccess等),没辙,只好提供了。
Ⅱ 如何关闭线程
关闭线程有几种方法, 一种是调用它里面的stop()方法 另一种就是你自己设置一个停止线程的标记 (推荐这种) 代码如下: package com.demo; //测试Thread的stop方法和自己编写一个停止标记来停止线程; public class StopThread implements Runnable{ //停止线程的标记值boolean; private boolean flag = true; public void stopThread(){ flag = false; } public void run(){ int i=0; while(flag){ i++; System.out.println(Thread.currentThread().getName()+":"+i); try{ Thread.sleep(1000); }catch(Exception e){ } System.out.println(Thread.currentThread().getName()+"==>"+i); } } public static void main(String args[]){ StopThread st = new StopThread(); Thread th = new Thread(st); Thread th1 = new Thread(st); th.start(); th1.start(); try{ Thread.sleep(5500); }catch(Exception e){ } /* 如果使用Thread.stop方法停止线程,不能保证这个线程是否完整的运行完成一次 run方法;但是如果使用停止的标记位,那么可以保正在真正停止之前完整的运行完 成一次run方法; */ th.stop(); st.stopThread(); } }
Ⅲ 如何正确结束Java线程
在Java的多线程编程中,java.lang.Thread类型包含了一些列的方法start(), stop(), stop(Throwable) and
suspend(), destroy() and
resume()。
通过这些方法,可以对线程进行方便的操作,但是这些方法中,只有start()方法得到了保留。
1.使用共享变量的方式
在这种方式中,之所以引入共享变量,是因为该变量可以被多个执行相同任务的线程用来作为是否中断的信号,通知中断线程的执行。
{
publicvolatilebooleanexit=false;
publicvoidrun()
{
while(!exit);
}
publicstaticvoidmain(String[]args)throwsException
{
ThreadFlagthread=newThreadFlag();
thread.start();
sleep(3000);//主线程延迟3秒
thread.exit=true;//终止线程thread
thread.join();
System.out.println("线程退出!");
}
}
在上面代码中定义了一个退出标志exit,当exit为true时,while循环退出,exit的默认值为false。在定义exit时,使用了一个Java关键字volatile,这个关键字的目的是使exit同步,也就是说在同一时刻只能由一个线程来修改exit的值。
privatevolatileThreadblinker;
publicvoidstop(){
blinker=null;
}
publicvoidrun(){
ThreadthisThread=Thread.currentThread();
while(blinker==thisThread){
try{
thisThread.sleep(interval);
}catch(InterruptedExceptione){
}
repaint();
}
}
2. 使用interrupt方法终止线程
如果一个线程由于等待某些事件的发生而被阻塞,又该怎样停止该线程呢?
这种情况经常会发生,比如当一个线程由于需要等候键盘输入而被阻塞,或者调用Thread.join()方法,或者Thread.sleep()方法,在网络中调用ServerSocket.accept()方法,或者调用了DatagramSocket.receive()方法时,都有可能导致线程阻塞,使线程处于处于不可运行状态时,即使主程序中将该线程的共享变量设置为true,但该线程此时根本无法检查循环标志,当然也就无法立即中断。
这里我们给出的建议是,不要使用stop()方法,而是使用Thread提供的interrupt()方法,因为该方法虽然不会中断一个正在运行的线程,但是它可以使一个被阻塞的线程抛出一个中断异常,从而使线程提前结束阻塞状态,退出堵塞代码。
classMyThreadextendsThread{
volatilebooleanstop=false;
publicvoidrun(){
while(!stop){
System.out.println(getName()+"isrunning");
try{
sleep(1000);
}catch(InterruptedExceptione){
System.out.println("weekupfromblcok...");
stop=true;//在异常处理代码中修改共享变量的状态
}
}
System.out.println(getName()+"isexiting...");
}
}
classInterruptThreadDemo3{
publicstaticvoidmain(String[]args)throwsInterruptedException{
MyThreadm1=newMyThread();
System.out.println("Startingthread...");
m1.start();
Thread.sleep(3000);
System.out.println("Interruptthread...:"+m1.getName());
m1.stop=true;//设置共享变量为true
m1.interrupt();//阻塞时退出阻塞状态
Thread.sleep(3000);//主线程休眠3秒以便观察线程m1的中断情况
System.out.println("Stoppingapplication...");
}
}
注意:在Thread类中有两个方法可以判断线程是否通过interrupt方法被终止。一个是静态的方法interrupted(),一个是非静态的方法isInterrupted(),这两个方法的区别是interrupted用来判断当前线是否被中断,而isInterrupted可以用来判断其他线程是否被中断。
Ⅳ C语言如何终止线程
终止线程有三种方法:
1.线程可以在自身内部调用AfxEndThread()来终止自身的运行
2.可以在线程的外部调用BOOL TerminateThread( HANDLE hThread, DWORD dwExitCode )来强行终止一个线程的运行,
然后调用CloseHandle()函数释放线程所占用的堆栈
3.第三种方法是改变全局变量,使线程的执行函数返回,则该线程终止。
unsigned long __cdecl _beginthread (void (__cdecl *) (void *),
unsigned, void *);
void __cdecl _endthread(void);
unsigned long __cdecl _beginthreadex(void *, unsigned,
unsigned (__stdcall *) (void *), void *, unsigned, unsigned *);
void __cdecl _endthreadex(unsigned);
找到的一些资料,希望有点帮助,要不你代码贴点出来
Ⅳ C语言如何终止线程
调用ExitThread函数。
该函数将终止线程的运行,并导致操作系统清除该线程使用的所有操作系统资源。但是,C++资源(如C++类对象)将不被撤消。
(3) 调用TerminateThread函数。
TerminateThread 能撤消任何线程。线程的内核对象的使用计数也被递减。TerminateThread函数是异步运行的函数。如果要确切地知道该线程已经终止运行,必须调用WaitForSingleObject或者类似的函数。当使用返回或调用ExitThread的方法撤消线程时,该线程的内存堆栈也被撤消。但是,如果使用TerminateThread,那么在拥有线程的进程终止运行之前,系统不撤消该线程的堆栈。
Ⅵ java 线程退出
为什么按回车才退出呢?因为你按回车了它才收到你输入的数据呀。
所以,你这个是交互场景设计错了
Ⅶ 线程有 exit方法吗
没有,那是系统的方法一般用system.exit(0)
Ⅷ 如何安全终止线程
终止线程
有两种情况可以使线程结束:控制函数结束或者根本就不允许线程完成,而提前终止它。我们可以想象在WORD中进行后台打印,如果打印结束了,那线程就可以结束了。如果用户中止了打印,那后台打印线程也要终止了。本文将主要介绍对这两种情况的实现,并且介绍如何获得线程的结束代码。
对于工作线程,结束它是比较容易的:退出线程函数然后返回一个结束原因的代码就是了。用户可以使用AfxEndThread函数或直接利用return返回。通常0代表成功返回,这不是硬性规定,一切要取决于你了。对于用户界面线程,调用::PostQuitMessage,它所要的唯一的参数就是返回代码,也就是工作线程中的那个码,性质是一样的。0通常代表成功。
提前终止一个线程也不难:在线程函数中调用AfxEndThread就是了,其中要传入的参数就是返回代码。这会停止线程的执行,释放线程栈,及与线程相关的DLL,并从内存中删除线程对象。AfxEndThread必须在线程函数内调用,如果用户希望从一个线程结束另一个线程,则需要在两个线程间建立通信机制。
如果需要获得线程返回代码,只需要调用::GetExitCodeThread就可以了。这个函数的具体作用就看大家具体去查帮助了。它传入的是线程的句柄,和一个提向返回代码的指针。将来就从那个指针得到返回代码。如果线程仍然处于活动状态,那么::GetExitCodeThread得到的返回代码为STILL_ACTIVE,如果已经退出则得到的是返回代码的地址。获得CWinThread对象的返回代码还需要一点麻烦,通常,当CWinThread线程结束时,线程对象就删除了,因为这个对象不存在了,也就没有办法访问对象的m_hThread变量了,为了避免这种情况,可以有两种方法:
将m_bAutoDelete设置为FALSE,这使得线程结束后CWinThread对象仍然存在,这样用户就可以访问m_hThread了,但是如果用户使用这种方法,用户需要自己析构CWinThread对象。这种方法是推荐的方法。
下一个方法是另外保存线程的句柄。在线程创建后,将m_hThread保存在另一个变量中,以后访问这个变量就是了。但是要小心,在复制句柄以前线程并没有结束,最安全的方法是在AfxBeginThread中传入CREATE_SUSPENDED,保存句柄,然后通过调用ResumeThread,重新开始线程。这两种方法都可以帮助用户得到CWinThread对象的返回代码。
对于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 = AfxGetMoleThreadState();
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;
}