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