{
// TODO: Add your command handler code here
hRunThread = CreateThread (NULL, 0, (LPTHREAD_START_ROUTINE)&pRunExcelThread, (void *)this, 0, &dwRunThreadID);
// 程序运行完提示
}
UINT pRunExcelThread (void* p)
{
pMF->FindAllFiles (clsDtC.acGetDtFolder (), //此函数执行很慢
clsDtC.acGetDtProcessedFolder (),
clsDtC.acGetDtErrorFolder (), pAdCn);
::PostMessage ( pMF->m_hWnd, WM_END_THREAD, (WPARAM) 0, (LPARAM) 0); //这里报异常
return 0;
}
这是我自定义的消息:
LONG CMainFrame::OnEndThread (WPARAM w, LPARAM l)
{
WaitForSingleObject (hRunThread, INFINITE);
if (NULL != hRunThread)
CloseHandle (hRunThread);
hRunThread = NULL;
return 0;
}
请问该如何修改~~~~~~~~~~~~~~
16 个解决方案
#1
ExitThread()
#2
现在回答问题的人越来越少了
#3
线程内退出用 ExitThread
线程外退出用 TerminateThread(handle);但是这有个问题,资源释放不掉
所以需要采用发消息的方式,就是发一个消息给线程,让它自己退出来
while(g_run)
{
//do something
if(g_run)//分片等待
{
Sleep(sec);
}
else
break;
}
线程外退出用 TerminateThread(handle);但是这有个问题,资源释放不掉
所以需要采用发消息的方式,就是发一个消息给线程,让它自己退出来
while(g_run)
{
//do something
if(g_run)//分片等待
{
Sleep(sec);
}
else
break;
}
#4
ls的意思在我的线程里加个
while(g_run)
{
pMF-> FindAllFiles (clsDtC.acGetDtFolder ()) //此函数执行很慢
g_run = false;
if(g_run)//分片等待
{
Sleep(sec);
}
else
break;
}
return 0;
是这样吗?
while(g_run)
{
pMF-> FindAllFiles (clsDtC.acGetDtFolder ()) //此函数执行很慢
g_run = false;
if(g_run)//分片等待
{
Sleep(sec);
}
else
break;
}
return 0;
是这样吗?
#5
要是这样的话
在void CMainFrame::OnImport() 这个函数里面
我怎么知道线程是否执行完呢?我要在执行完输出一端话:
void CMainFrame::OnImport() /************这是菜单的响应消息*******************************************
{
// TODO: Add your command handler code here
hRunThread = CreateThread (NULL, 0, (LPTHREAD_START_ROUTINE)&pRunExcelThread, (void *)this, 0, &dwRunThreadID);
// 输出一段话
}
在void CMainFrame::OnImport() 这个函数里面
我怎么知道线程是否执行完呢?我要在执行完输出一端话:
void CMainFrame::OnImport() /************这是菜单的响应消息*******************************************
{
// TODO: Add your command handler code here
hRunThread = CreateThread (NULL, 0, (LPTHREAD_START_ROUTINE)&pRunExcelThread, (void *)this, 0, &dwRunThreadID);
// 输出一段话
}
#6
直接在你想退出的地方return就可以了.
#7
都没明白我的意思吗?
void CMainFrame::OnImport() /************这是菜单的响应消息*******************************************
{
// TODO: Add your command handler code here
hRunThread = CreateThread (NULL, 0, (LPTHREAD_START_ROUTINE)&pRunExcelThread, (void *)this, 0, &dwRunThreadID);
// 输出一段话 ,(线程里当然知道return,这里我怎么在return后打印这段话)
}
void CMainFrame::OnImport() /************这是菜单的响应消息*******************************************
{
// TODO: Add your command handler code here
hRunThread = CreateThread (NULL, 0, (LPTHREAD_START_ROUTINE)&pRunExcelThread, (void *)this, 0, &dwRunThreadID);
// 输出一段话 ,(线程里当然知道return,这里我怎么在return后打印这段话)
}
#8
烦了,,高手都哪去了
我界面为什么没响应了。
我界面为什么没响应了。
#9
你可以用
DWORD WaitForSingleObject(
HANDLE hHandle,
DWORD dwMilliseconds
);
来等待线程的句柄
WaitForSingleObject(
hThread,
TimeOut
);
DWORD WaitForSingleObject(
HANDLE hHandle,
DWORD dwMilliseconds
);
来等待线程的句柄
WaitForSingleObject(
hThread,
TimeOut
);
#10
这个问题非常简单,大师说了,好的线程结束设计,就是让线程自己return返回释放。
你要懂! 所谓的TerminalThread不是推荐的方法,因为会导致内存泄漏等问题。
想要知道何时返回,就要用到雁南双星所说的waitForSingleObject,或者waitForMultipleObject。。。
Any Porblem?
你要懂! 所谓的TerminalThread不是推荐的方法,因为会导致内存泄漏等问题。
想要知道何时返回,就要用到雁南双星所说的waitForSingleObject,或者waitForMultipleObject。。。
Any Porblem?
#11
同意楼上的言论.
#12
楼主的方法看起来可以啊。
::PostMessage ( pMF-> m_hWnd, WM_END_THREAD, (WPARAM) 0, (LPARAM) 0);
抛的什么异常?
::PostMessage ( pMF-> m_hWnd, WM_END_THREAD, (WPARAM) 0, (LPARAM) 0);
抛的什么异常?
#13
return 返回
#14
《Visual C++ 6.0 编程实例与技巧》里面讲得清楚,你找来看看
#15
本来想写给你的,但太多,呵呵呵呵呵
#16
写到一半的时候,停电了 昏啊
干脆帖点过来 ^_^
选自《Windows 核心编程》,顺便推荐一下
.5 终止线程的运行
若要终止线程的运行,可以使用下面的方法:
• 线程函数返回(最好使用这种方法)。
• 通过调用E x i t T h r e a d函数,线程将自行撤消(最好不要使用这种方法)。
• 同一个进程或另一个进程中的线程调用Te r m i n a t e T h r e a d函数(应该避免使用这种方法)。
• 包含线程的进程终止运行(应该避免使用这种方法)。
下面将介绍终止线程运行的方法,并且说明线程终止运行时会出现什么情况。
6.5.1 线程函数返回
始终都应该将线程设计成这样的形式,即当想要线程终止运行时,它们就能够返回。这是确保所有线程资源被正确地清除的唯一办法。
如果线程能够返回,就可以确保下列事项的实现:
• 在线程函数中创建的所有C + +对象均将通过它们的撤消函数正确地撤消。
• 操作系统将正确地释放线程堆栈使用的内存。
• 系统将线程的退出代码(在线程的内核对象中维护)设置为线程函数的返回值。
• 系统将递减线程内核对象的使用计数。
6.5.2 ExitThread函数
可以让线程调用E x i t T h r e a d函数,以便强制线程终止运行:
VOID ExitThread(DWORD dwExitCode);
该函数将终止线程的运行,并导致操作系统清除该线程使用的所有操作系统资源。但是,C + +资源(如C + +类对象)将不被撤消。由于这个原因,最好从线程函数返回,而不是通过调用E x i t T h r e a d来返回(详细说明参见第4章)。
当然,可以使用E x i t T h r e a d的d w E x i t T h r e a d参数告诉系统将线程的退出代码设置为什么。E x i t T h r e a d函数并不返回任何值,因为线程已经终止运行,不能执行更多的代码。
注意终止线程运行的最佳方法是让它的线程函数返回。但是,如果使用本节介绍的方法,应该知道E x i t T h r e a d函数是Wi n d o w s用来撤消线程的函数。如果编写C / C + +代码,那么决不应该调用E x i t T h r e a d。应该使用Visual C++运行期库函数_ e n d t h r e a d e x。如果不使用M i c r o s o f t的Visual C++编译器,你的编译器供应商有它自己的E x i t T h r e a d的替代函数。不管这个替代函数是什么,都必须使用。本章后面将说明_ e n d t h r e a d e x的作用和它的重要性。
6.5.3 TerminateThread函数
调用Te r m i n a t e T h r e a d函数也能够终止线程的运行:
BOOL TerminateThread(
HANDLE hThread,
DWORD dwExitCode);
与E x i t T h r e a d不同,E x i t T h r e a d总是撤消调用的线程,而Te r m i n a t e T h r e a d能够撤消任何线程。h T h r e a d参数用于标识被终止运行的线程的句柄。当线程终止运行时,它的退出代码成为你作为d w E x i t C o d e参数传递的值。同时,线程的内核对象的使用计数也被递减。
注意Te r m i n a t e T h r e a d函数是异步运行的函数,也就是说,它告诉系统你想要线程终止运行,但是,当函数返回时,不能保证线程被撤消。如果需要确切地知道该线程已经终止运行,必须调用Wa i t F o r S i n g l e O b j e c t (第9章介绍)或者类似的函数,传递线程的句柄。
设计良好的应用程序从来不使用这个函数,因为被终止运行的线程收不到它被撤消的通知。线程不能正确地清除,并且不能防止自己被撤消。
注意当使用返回或调用E x i t T h r e a d的方法撤消线程时,该线程的内存堆栈也被撤消。但是,如果使用Te r m i n a t e T h r e a d,那么在拥有线程的进程终止运行之前,系统不撤消该线程的堆栈。M i c r o s o f t故意用这种方法来实现Te r m i n a t e T h r e a d。如果其他仍然正在执行的线程要引用强制撤消的线程堆栈上的值,那么其他的线程就会出现访问违规的问题。如果将已经撤消的线程的堆栈留在内存中,那么其他线程就可以继续很好地运行。
此外,当线程终止运行时, D L L通常接收通知。如果使用Terminate Thread 强迫线程终止,D L L就不接收通知,这能阻止适当的清除(详细信息参见第2 0章)
6.5.4 在进程终止运行时撤消线程
第4章介绍的E x i t P r o c e s s和Te r m i n a t e P r o c e s s函数也可以用来终止线程的运行。差别在于这些线程将会使终止运行的进程中的所有线程全部终止运行。另外,由于整个进程已经被关闭,进程使用的所有资源肯定已被清除。这当然包括所有线程的堆栈。这两个函数会导致进程中的剩余线程被强制撤消,就像从每个剩余的线程调用Te r m i n a t e T h r e a d一样。显然,这意味着正确的应用程序清除没有发生,即C + +对象撤消函数没有被调用,数据没有转至磁盘等等。
6.5.5 线程终止运行时发生的操作
当线程终止运行时,会发生下列操作:
• 线程拥有的所有用户对象均被释放。在Wi n d o w s中,大多数对象是由包含创建这些对象的线程的进程拥有的。但是一个线程拥有两个用户对象,即窗口和挂钩。当线程终止运行时,系统会自动撤消任何窗口,并且卸载线程创建的或安装的任何挂钩。其他对象只有在拥有线程的进程终止运行时才被撤消。
• 线程的退出代码从S T I L L _ A C T I V E改为传递给E x i t T h r e a d或Te r m i n a t e T h r e a d的代码。
• 线程内核对象的状态变为已通知。
• 如果线程是进程中最后一个活动线程,系统也将进程视为已经终止运行。
• 线程内核对象的使用计数递减1。
当一个线程终止运行时,在与它相关联的线程内核对象的所有未结束的引用关闭之前,该内核对象不会自动被释放。
一旦线程不再运行,系统中就没有别的线程能够处理该线程的句柄。然而别的线程可以调用G e t E x i t c o d e T h r e a d来检查由h T h r e a d标识的线程是否已经终止运行。如果它已经终止运行,则确定它的退出代码:
BOOL GetExitCodeThread(
HANDLE hThread,
PDWORD pdwExitCode);
退出代码的值在p d w E x i t C o d e指向的D W O R D中返回。如果调用G e t E x i t C o d e T h r e a d时线程尚未终止运行,该函数就用S T I L L _ A C T I V E标识符(定义为0 x 1 0 3)填入D W O R D。如果该函数运行成功,便返回T R U E(第9章将详细地介绍如何使用线程的句柄来确定何时线程终止运行)。
干脆帖点过来 ^_^
选自《Windows 核心编程》,顺便推荐一下
.5 终止线程的运行
若要终止线程的运行,可以使用下面的方法:
• 线程函数返回(最好使用这种方法)。
• 通过调用E x i t T h r e a d函数,线程将自行撤消(最好不要使用这种方法)。
• 同一个进程或另一个进程中的线程调用Te r m i n a t e T h r e a d函数(应该避免使用这种方法)。
• 包含线程的进程终止运行(应该避免使用这种方法)。
下面将介绍终止线程运行的方法,并且说明线程终止运行时会出现什么情况。
6.5.1 线程函数返回
始终都应该将线程设计成这样的形式,即当想要线程终止运行时,它们就能够返回。这是确保所有线程资源被正确地清除的唯一办法。
如果线程能够返回,就可以确保下列事项的实现:
• 在线程函数中创建的所有C + +对象均将通过它们的撤消函数正确地撤消。
• 操作系统将正确地释放线程堆栈使用的内存。
• 系统将线程的退出代码(在线程的内核对象中维护)设置为线程函数的返回值。
• 系统将递减线程内核对象的使用计数。
6.5.2 ExitThread函数
可以让线程调用E x i t T h r e a d函数,以便强制线程终止运行:
VOID ExitThread(DWORD dwExitCode);
该函数将终止线程的运行,并导致操作系统清除该线程使用的所有操作系统资源。但是,C + +资源(如C + +类对象)将不被撤消。由于这个原因,最好从线程函数返回,而不是通过调用E x i t T h r e a d来返回(详细说明参见第4章)。
当然,可以使用E x i t T h r e a d的d w E x i t T h r e a d参数告诉系统将线程的退出代码设置为什么。E x i t T h r e a d函数并不返回任何值,因为线程已经终止运行,不能执行更多的代码。
注意终止线程运行的最佳方法是让它的线程函数返回。但是,如果使用本节介绍的方法,应该知道E x i t T h r e a d函数是Wi n d o w s用来撤消线程的函数。如果编写C / C + +代码,那么决不应该调用E x i t T h r e a d。应该使用Visual C++运行期库函数_ e n d t h r e a d e x。如果不使用M i c r o s o f t的Visual C++编译器,你的编译器供应商有它自己的E x i t T h r e a d的替代函数。不管这个替代函数是什么,都必须使用。本章后面将说明_ e n d t h r e a d e x的作用和它的重要性。
6.5.3 TerminateThread函数
调用Te r m i n a t e T h r e a d函数也能够终止线程的运行:
BOOL TerminateThread(
HANDLE hThread,
DWORD dwExitCode);
与E x i t T h r e a d不同,E x i t T h r e a d总是撤消调用的线程,而Te r m i n a t e T h r e a d能够撤消任何线程。h T h r e a d参数用于标识被终止运行的线程的句柄。当线程终止运行时,它的退出代码成为你作为d w E x i t C o d e参数传递的值。同时,线程的内核对象的使用计数也被递减。
注意Te r m i n a t e T h r e a d函数是异步运行的函数,也就是说,它告诉系统你想要线程终止运行,但是,当函数返回时,不能保证线程被撤消。如果需要确切地知道该线程已经终止运行,必须调用Wa i t F o r S i n g l e O b j e c t (第9章介绍)或者类似的函数,传递线程的句柄。
设计良好的应用程序从来不使用这个函数,因为被终止运行的线程收不到它被撤消的通知。线程不能正确地清除,并且不能防止自己被撤消。
注意当使用返回或调用E x i t T h r e a d的方法撤消线程时,该线程的内存堆栈也被撤消。但是,如果使用Te r m i n a t e T h r e a d,那么在拥有线程的进程终止运行之前,系统不撤消该线程的堆栈。M i c r o s o f t故意用这种方法来实现Te r m i n a t e T h r e a d。如果其他仍然正在执行的线程要引用强制撤消的线程堆栈上的值,那么其他的线程就会出现访问违规的问题。如果将已经撤消的线程的堆栈留在内存中,那么其他线程就可以继续很好地运行。
此外,当线程终止运行时, D L L通常接收通知。如果使用Terminate Thread 强迫线程终止,D L L就不接收通知,这能阻止适当的清除(详细信息参见第2 0章)
6.5.4 在进程终止运行时撤消线程
第4章介绍的E x i t P r o c e s s和Te r m i n a t e P r o c e s s函数也可以用来终止线程的运行。差别在于这些线程将会使终止运行的进程中的所有线程全部终止运行。另外,由于整个进程已经被关闭,进程使用的所有资源肯定已被清除。这当然包括所有线程的堆栈。这两个函数会导致进程中的剩余线程被强制撤消,就像从每个剩余的线程调用Te r m i n a t e T h r e a d一样。显然,这意味着正确的应用程序清除没有发生,即C + +对象撤消函数没有被调用,数据没有转至磁盘等等。
6.5.5 线程终止运行时发生的操作
当线程终止运行时,会发生下列操作:
• 线程拥有的所有用户对象均被释放。在Wi n d o w s中,大多数对象是由包含创建这些对象的线程的进程拥有的。但是一个线程拥有两个用户对象,即窗口和挂钩。当线程终止运行时,系统会自动撤消任何窗口,并且卸载线程创建的或安装的任何挂钩。其他对象只有在拥有线程的进程终止运行时才被撤消。
• 线程的退出代码从S T I L L _ A C T I V E改为传递给E x i t T h r e a d或Te r m i n a t e T h r e a d的代码。
• 线程内核对象的状态变为已通知。
• 如果线程是进程中最后一个活动线程,系统也将进程视为已经终止运行。
• 线程内核对象的使用计数递减1。
当一个线程终止运行时,在与它相关联的线程内核对象的所有未结束的引用关闭之前,该内核对象不会自动被释放。
一旦线程不再运行,系统中就没有别的线程能够处理该线程的句柄。然而别的线程可以调用G e t E x i t c o d e T h r e a d来检查由h T h r e a d标识的线程是否已经终止运行。如果它已经终止运行,则确定它的退出代码:
BOOL GetExitCodeThread(
HANDLE hThread,
PDWORD pdwExitCode);
退出代码的值在p d w E x i t C o d e指向的D W O R D中返回。如果调用G e t E x i t C o d e T h r e a d时线程尚未终止运行,该函数就用S T I L L _ A C T I V E标识符(定义为0 x 1 0 3)填入D W O R D。如果该函数运行成功,便返回T R U E(第9章将详细地介绍如何使用线程的句柄来确定何时线程终止运行)。
#1
ExitThread()
#2
现在回答问题的人越来越少了
#3
线程内退出用 ExitThread
线程外退出用 TerminateThread(handle);但是这有个问题,资源释放不掉
所以需要采用发消息的方式,就是发一个消息给线程,让它自己退出来
while(g_run)
{
//do something
if(g_run)//分片等待
{
Sleep(sec);
}
else
break;
}
线程外退出用 TerminateThread(handle);但是这有个问题,资源释放不掉
所以需要采用发消息的方式,就是发一个消息给线程,让它自己退出来
while(g_run)
{
//do something
if(g_run)//分片等待
{
Sleep(sec);
}
else
break;
}
#4
ls的意思在我的线程里加个
while(g_run)
{
pMF-> FindAllFiles (clsDtC.acGetDtFolder ()) //此函数执行很慢
g_run = false;
if(g_run)//分片等待
{
Sleep(sec);
}
else
break;
}
return 0;
是这样吗?
while(g_run)
{
pMF-> FindAllFiles (clsDtC.acGetDtFolder ()) //此函数执行很慢
g_run = false;
if(g_run)//分片等待
{
Sleep(sec);
}
else
break;
}
return 0;
是这样吗?
#5
要是这样的话
在void CMainFrame::OnImport() 这个函数里面
我怎么知道线程是否执行完呢?我要在执行完输出一端话:
void CMainFrame::OnImport() /************这是菜单的响应消息*******************************************
{
// TODO: Add your command handler code here
hRunThread = CreateThread (NULL, 0, (LPTHREAD_START_ROUTINE)&pRunExcelThread, (void *)this, 0, &dwRunThreadID);
// 输出一段话
}
在void CMainFrame::OnImport() 这个函数里面
我怎么知道线程是否执行完呢?我要在执行完输出一端话:
void CMainFrame::OnImport() /************这是菜单的响应消息*******************************************
{
// TODO: Add your command handler code here
hRunThread = CreateThread (NULL, 0, (LPTHREAD_START_ROUTINE)&pRunExcelThread, (void *)this, 0, &dwRunThreadID);
// 输出一段话
}
#6
直接在你想退出的地方return就可以了.
#7
都没明白我的意思吗?
void CMainFrame::OnImport() /************这是菜单的响应消息*******************************************
{
// TODO: Add your command handler code here
hRunThread = CreateThread (NULL, 0, (LPTHREAD_START_ROUTINE)&pRunExcelThread, (void *)this, 0, &dwRunThreadID);
// 输出一段话 ,(线程里当然知道return,这里我怎么在return后打印这段话)
}
void CMainFrame::OnImport() /************这是菜单的响应消息*******************************************
{
// TODO: Add your command handler code here
hRunThread = CreateThread (NULL, 0, (LPTHREAD_START_ROUTINE)&pRunExcelThread, (void *)this, 0, &dwRunThreadID);
// 输出一段话 ,(线程里当然知道return,这里我怎么在return后打印这段话)
}
#8
烦了,,高手都哪去了
我界面为什么没响应了。
我界面为什么没响应了。
#9
你可以用
DWORD WaitForSingleObject(
HANDLE hHandle,
DWORD dwMilliseconds
);
来等待线程的句柄
WaitForSingleObject(
hThread,
TimeOut
);
DWORD WaitForSingleObject(
HANDLE hHandle,
DWORD dwMilliseconds
);
来等待线程的句柄
WaitForSingleObject(
hThread,
TimeOut
);
#10
这个问题非常简单,大师说了,好的线程结束设计,就是让线程自己return返回释放。
你要懂! 所谓的TerminalThread不是推荐的方法,因为会导致内存泄漏等问题。
想要知道何时返回,就要用到雁南双星所说的waitForSingleObject,或者waitForMultipleObject。。。
Any Porblem?
你要懂! 所谓的TerminalThread不是推荐的方法,因为会导致内存泄漏等问题。
想要知道何时返回,就要用到雁南双星所说的waitForSingleObject,或者waitForMultipleObject。。。
Any Porblem?
#11
同意楼上的言论.
#12
楼主的方法看起来可以啊。
::PostMessage ( pMF-> m_hWnd, WM_END_THREAD, (WPARAM) 0, (LPARAM) 0);
抛的什么异常?
::PostMessage ( pMF-> m_hWnd, WM_END_THREAD, (WPARAM) 0, (LPARAM) 0);
抛的什么异常?
#13
return 返回
#14
《Visual C++ 6.0 编程实例与技巧》里面讲得清楚,你找来看看
#15
本来想写给你的,但太多,呵呵呵呵呵
#16
写到一半的时候,停电了 昏啊
干脆帖点过来 ^_^
选自《Windows 核心编程》,顺便推荐一下
.5 终止线程的运行
若要终止线程的运行,可以使用下面的方法:
• 线程函数返回(最好使用这种方法)。
• 通过调用E x i t T h r e a d函数,线程将自行撤消(最好不要使用这种方法)。
• 同一个进程或另一个进程中的线程调用Te r m i n a t e T h r e a d函数(应该避免使用这种方法)。
• 包含线程的进程终止运行(应该避免使用这种方法)。
下面将介绍终止线程运行的方法,并且说明线程终止运行时会出现什么情况。
6.5.1 线程函数返回
始终都应该将线程设计成这样的形式,即当想要线程终止运行时,它们就能够返回。这是确保所有线程资源被正确地清除的唯一办法。
如果线程能够返回,就可以确保下列事项的实现:
• 在线程函数中创建的所有C + +对象均将通过它们的撤消函数正确地撤消。
• 操作系统将正确地释放线程堆栈使用的内存。
• 系统将线程的退出代码(在线程的内核对象中维护)设置为线程函数的返回值。
• 系统将递减线程内核对象的使用计数。
6.5.2 ExitThread函数
可以让线程调用E x i t T h r e a d函数,以便强制线程终止运行:
VOID ExitThread(DWORD dwExitCode);
该函数将终止线程的运行,并导致操作系统清除该线程使用的所有操作系统资源。但是,C + +资源(如C + +类对象)将不被撤消。由于这个原因,最好从线程函数返回,而不是通过调用E x i t T h r e a d来返回(详细说明参见第4章)。
当然,可以使用E x i t T h r e a d的d w E x i t T h r e a d参数告诉系统将线程的退出代码设置为什么。E x i t T h r e a d函数并不返回任何值,因为线程已经终止运行,不能执行更多的代码。
注意终止线程运行的最佳方法是让它的线程函数返回。但是,如果使用本节介绍的方法,应该知道E x i t T h r e a d函数是Wi n d o w s用来撤消线程的函数。如果编写C / C + +代码,那么决不应该调用E x i t T h r e a d。应该使用Visual C++运行期库函数_ e n d t h r e a d e x。如果不使用M i c r o s o f t的Visual C++编译器,你的编译器供应商有它自己的E x i t T h r e a d的替代函数。不管这个替代函数是什么,都必须使用。本章后面将说明_ e n d t h r e a d e x的作用和它的重要性。
6.5.3 TerminateThread函数
调用Te r m i n a t e T h r e a d函数也能够终止线程的运行:
BOOL TerminateThread(
HANDLE hThread,
DWORD dwExitCode);
与E x i t T h r e a d不同,E x i t T h r e a d总是撤消调用的线程,而Te r m i n a t e T h r e a d能够撤消任何线程。h T h r e a d参数用于标识被终止运行的线程的句柄。当线程终止运行时,它的退出代码成为你作为d w E x i t C o d e参数传递的值。同时,线程的内核对象的使用计数也被递减。
注意Te r m i n a t e T h r e a d函数是异步运行的函数,也就是说,它告诉系统你想要线程终止运行,但是,当函数返回时,不能保证线程被撤消。如果需要确切地知道该线程已经终止运行,必须调用Wa i t F o r S i n g l e O b j e c t (第9章介绍)或者类似的函数,传递线程的句柄。
设计良好的应用程序从来不使用这个函数,因为被终止运行的线程收不到它被撤消的通知。线程不能正确地清除,并且不能防止自己被撤消。
注意当使用返回或调用E x i t T h r e a d的方法撤消线程时,该线程的内存堆栈也被撤消。但是,如果使用Te r m i n a t e T h r e a d,那么在拥有线程的进程终止运行之前,系统不撤消该线程的堆栈。M i c r o s o f t故意用这种方法来实现Te r m i n a t e T h r e a d。如果其他仍然正在执行的线程要引用强制撤消的线程堆栈上的值,那么其他的线程就会出现访问违规的问题。如果将已经撤消的线程的堆栈留在内存中,那么其他线程就可以继续很好地运行。
此外,当线程终止运行时, D L L通常接收通知。如果使用Terminate Thread 强迫线程终止,D L L就不接收通知,这能阻止适当的清除(详细信息参见第2 0章)
6.5.4 在进程终止运行时撤消线程
第4章介绍的E x i t P r o c e s s和Te r m i n a t e P r o c e s s函数也可以用来终止线程的运行。差别在于这些线程将会使终止运行的进程中的所有线程全部终止运行。另外,由于整个进程已经被关闭,进程使用的所有资源肯定已被清除。这当然包括所有线程的堆栈。这两个函数会导致进程中的剩余线程被强制撤消,就像从每个剩余的线程调用Te r m i n a t e T h r e a d一样。显然,这意味着正确的应用程序清除没有发生,即C + +对象撤消函数没有被调用,数据没有转至磁盘等等。
6.5.5 线程终止运行时发生的操作
当线程终止运行时,会发生下列操作:
• 线程拥有的所有用户对象均被释放。在Wi n d o w s中,大多数对象是由包含创建这些对象的线程的进程拥有的。但是一个线程拥有两个用户对象,即窗口和挂钩。当线程终止运行时,系统会自动撤消任何窗口,并且卸载线程创建的或安装的任何挂钩。其他对象只有在拥有线程的进程终止运行时才被撤消。
• 线程的退出代码从S T I L L _ A C T I V E改为传递给E x i t T h r e a d或Te r m i n a t e T h r e a d的代码。
• 线程内核对象的状态变为已通知。
• 如果线程是进程中最后一个活动线程,系统也将进程视为已经终止运行。
• 线程内核对象的使用计数递减1。
当一个线程终止运行时,在与它相关联的线程内核对象的所有未结束的引用关闭之前,该内核对象不会自动被释放。
一旦线程不再运行,系统中就没有别的线程能够处理该线程的句柄。然而别的线程可以调用G e t E x i t c o d e T h r e a d来检查由h T h r e a d标识的线程是否已经终止运行。如果它已经终止运行,则确定它的退出代码:
BOOL GetExitCodeThread(
HANDLE hThread,
PDWORD pdwExitCode);
退出代码的值在p d w E x i t C o d e指向的D W O R D中返回。如果调用G e t E x i t C o d e T h r e a d时线程尚未终止运行,该函数就用S T I L L _ A C T I V E标识符(定义为0 x 1 0 3)填入D W O R D。如果该函数运行成功,便返回T R U E(第9章将详细地介绍如何使用线程的句柄来确定何时线程终止运行)。
干脆帖点过来 ^_^
选自《Windows 核心编程》,顺便推荐一下
.5 终止线程的运行
若要终止线程的运行,可以使用下面的方法:
• 线程函数返回(最好使用这种方法)。
• 通过调用E x i t T h r e a d函数,线程将自行撤消(最好不要使用这种方法)。
• 同一个进程或另一个进程中的线程调用Te r m i n a t e T h r e a d函数(应该避免使用这种方法)。
• 包含线程的进程终止运行(应该避免使用这种方法)。
下面将介绍终止线程运行的方法,并且说明线程终止运行时会出现什么情况。
6.5.1 线程函数返回
始终都应该将线程设计成这样的形式,即当想要线程终止运行时,它们就能够返回。这是确保所有线程资源被正确地清除的唯一办法。
如果线程能够返回,就可以确保下列事项的实现:
• 在线程函数中创建的所有C + +对象均将通过它们的撤消函数正确地撤消。
• 操作系统将正确地释放线程堆栈使用的内存。
• 系统将线程的退出代码(在线程的内核对象中维护)设置为线程函数的返回值。
• 系统将递减线程内核对象的使用计数。
6.5.2 ExitThread函数
可以让线程调用E x i t T h r e a d函数,以便强制线程终止运行:
VOID ExitThread(DWORD dwExitCode);
该函数将终止线程的运行,并导致操作系统清除该线程使用的所有操作系统资源。但是,C + +资源(如C + +类对象)将不被撤消。由于这个原因,最好从线程函数返回,而不是通过调用E x i t T h r e a d来返回(详细说明参见第4章)。
当然,可以使用E x i t T h r e a d的d w E x i t T h r e a d参数告诉系统将线程的退出代码设置为什么。E x i t T h r e a d函数并不返回任何值,因为线程已经终止运行,不能执行更多的代码。
注意终止线程运行的最佳方法是让它的线程函数返回。但是,如果使用本节介绍的方法,应该知道E x i t T h r e a d函数是Wi n d o w s用来撤消线程的函数。如果编写C / C + +代码,那么决不应该调用E x i t T h r e a d。应该使用Visual C++运行期库函数_ e n d t h r e a d e x。如果不使用M i c r o s o f t的Visual C++编译器,你的编译器供应商有它自己的E x i t T h r e a d的替代函数。不管这个替代函数是什么,都必须使用。本章后面将说明_ e n d t h r e a d e x的作用和它的重要性。
6.5.3 TerminateThread函数
调用Te r m i n a t e T h r e a d函数也能够终止线程的运行:
BOOL TerminateThread(
HANDLE hThread,
DWORD dwExitCode);
与E x i t T h r e a d不同,E x i t T h r e a d总是撤消调用的线程,而Te r m i n a t e T h r e a d能够撤消任何线程。h T h r e a d参数用于标识被终止运行的线程的句柄。当线程终止运行时,它的退出代码成为你作为d w E x i t C o d e参数传递的值。同时,线程的内核对象的使用计数也被递减。
注意Te r m i n a t e T h r e a d函数是异步运行的函数,也就是说,它告诉系统你想要线程终止运行,但是,当函数返回时,不能保证线程被撤消。如果需要确切地知道该线程已经终止运行,必须调用Wa i t F o r S i n g l e O b j e c t (第9章介绍)或者类似的函数,传递线程的句柄。
设计良好的应用程序从来不使用这个函数,因为被终止运行的线程收不到它被撤消的通知。线程不能正确地清除,并且不能防止自己被撤消。
注意当使用返回或调用E x i t T h r e a d的方法撤消线程时,该线程的内存堆栈也被撤消。但是,如果使用Te r m i n a t e T h r e a d,那么在拥有线程的进程终止运行之前,系统不撤消该线程的堆栈。M i c r o s o f t故意用这种方法来实现Te r m i n a t e T h r e a d。如果其他仍然正在执行的线程要引用强制撤消的线程堆栈上的值,那么其他的线程就会出现访问违规的问题。如果将已经撤消的线程的堆栈留在内存中,那么其他线程就可以继续很好地运行。
此外,当线程终止运行时, D L L通常接收通知。如果使用Terminate Thread 强迫线程终止,D L L就不接收通知,这能阻止适当的清除(详细信息参见第2 0章)
6.5.4 在进程终止运行时撤消线程
第4章介绍的E x i t P r o c e s s和Te r m i n a t e P r o c e s s函数也可以用来终止线程的运行。差别在于这些线程将会使终止运行的进程中的所有线程全部终止运行。另外,由于整个进程已经被关闭,进程使用的所有资源肯定已被清除。这当然包括所有线程的堆栈。这两个函数会导致进程中的剩余线程被强制撤消,就像从每个剩余的线程调用Te r m i n a t e T h r e a d一样。显然,这意味着正确的应用程序清除没有发生,即C + +对象撤消函数没有被调用,数据没有转至磁盘等等。
6.5.5 线程终止运行时发生的操作
当线程终止运行时,会发生下列操作:
• 线程拥有的所有用户对象均被释放。在Wi n d o w s中,大多数对象是由包含创建这些对象的线程的进程拥有的。但是一个线程拥有两个用户对象,即窗口和挂钩。当线程终止运行时,系统会自动撤消任何窗口,并且卸载线程创建的或安装的任何挂钩。其他对象只有在拥有线程的进程终止运行时才被撤消。
• 线程的退出代码从S T I L L _ A C T I V E改为传递给E x i t T h r e a d或Te r m i n a t e T h r e a d的代码。
• 线程内核对象的状态变为已通知。
• 如果线程是进程中最后一个活动线程,系统也将进程视为已经终止运行。
• 线程内核对象的使用计数递减1。
当一个线程终止运行时,在与它相关联的线程内核对象的所有未结束的引用关闭之前,该内核对象不会自动被释放。
一旦线程不再运行,系统中就没有别的线程能够处理该线程的句柄。然而别的线程可以调用G e t E x i t c o d e T h r e a d来检查由h T h r e a d标识的线程是否已经终止运行。如果它已经终止运行,则确定它的退出代码:
BOOL GetExitCodeThread(
HANDLE hThread,
PDWORD pdwExitCode);
退出代码的值在p d w E x i t C o d e指向的D W O R D中返回。如果调用G e t E x i t C o d e T h r e a d时线程尚未终止运行,该函数就用S T I L L _ A C T I V E标识符(定义为0 x 1 0 3)填入D W O R D。如果该函数运行成功,便返回T R U E(第9章将详细地介绍如何使用线程的句柄来确定何时线程终止运行)。