读书人

怎么在一个线程中结束另一个线程

发布时间: 2012-02-10 21:27:42 作者: rapoo

如何在一个线程中结束另一个线程
以前我一直遵循老师教的方法, 在分线程中死循环判断一个BOOL变量, 主线程需要结束分线程时去设置这个BOOL变量的值使它自然退出

该方法分线程并不是立即被杀死的, 它必须走完此次循环到判断BOOL变量处才能结束

1. 如果有一些对象是主、分线程都要访问的, 那么可能在主线程中已经释放了它们而分线程任然访问它, 造成非法访问
2. 我有想过将这些对象的释放放在分线程判断BOOL变量退出线程时执行, 但是主线程的逻辑是很有可能在杀死分线程后又建立一个分线程, 此时根据这些对象是否存在而判断是否创建,这样旧的分线程暂时没有释放对象导致新线程建立时没有建立对象之后这些对象又被旧线程释放, 造成非法访问
3. 后来我又想在主线程wait分线程退出后再释放对象, 但如果分线程中有一些比较耗时的操作(例如IO。下载、解压等等), 那么主线程阻塞太久了

我想问问大家一般怎么解决这个问题。
1. 使用TerminateThread到底会导致哪些不良后果呢, 线程是否在TerminateThread执行结束后立即被杀死呢
我个人认为由于被杀死的线程不知道执行到何处, 可能会出现一些new了的资源、打开的句柄没有被释放, 不知道是否有其他坏处
2. 其他一些语言中封装好的线程类例如java中的interrupt是否也存在这个问题
3. 我现在遇到的问题是否都是因为主、分线程访问同一对象导致的(其实就相当于全局变量带来的危害一样), 是否应该完全避免
4. 大家在程序设计的时候一般都是怎么解决在一个线程中结束另一个线程的

[解决办法]
占座楼
[解决办法]
对于这种共享对象,楼主可以看看http://www.boost.org/doc/libs/1_47_0/libs/smart_ptr/smart_ptr.htm
一般是建议让线程自己退出,不强制杀死
[解决办法]
也许share_ptr是一个好东东
[解决办法]
1.具体就是这些泄露了,TerminateThread嘛,好像就是陷阱下去直接返回调用函数而不进行栈展开等,《核心编程》上对线程的结束类型有详细的讨论。
2.人家封装好的线程类了,这些保障还是会有的,要不JAVA也不会那么热,用户是不需要关心资源安全问题的(仅个人观点)。
3.不应该避免,细心点同步就行了,资源共享也是多线程一大亮点。
4.wait他自然结束,如果就像LZ说的比较耗时的操作,他耗时管你什么事,你close掉IO啊,反正你都要丢弃的了,这部分数据,如果不丢弃就等他传输完自然结束。

PS:最好新建一个wait线程负责wait然后处理收尾工作,避免在主线程wait而阻塞程序执行。

[解决办法]
一般是给线程添加一个Stop 的方法 ,将线程的一个变量设置为F .

线程在循环时检查这个变量,如果为F则退出。

在Stop 方法中,

FStop:=False; //设置状态
Resume;//让线程运行
WaitForSingleObject //等待线程结束

在就是用临界区来保证数据的安全。

要是一个对象多个线程访问,那最好就不要在这些线程中释放.应该在这些线程都结束后在进行。





[解决办法]
我的做法是——对于那种执行完一次不可能再执行的线程TerminateThread也不会有太大问题(内存泄漏一点点没什么,除非你在你面打开了文件句柄等内核对象,以后第二次打开会有问题)

对于可能要重复启动的线程,你干嘛要退出呢?,一只挂那里就行了,用个循环+wait阻塞住,需要的时候唤醒。

如果是进程结束,那更不用管了。

线程退出处理确实是个细活,难办的事情就绕过他

或者用线程池,退出别人帮你做好,Vista新加的几个线程池函数还有专门的扫尾回调函数,可以擦屁股

线程正规的使用方式就不是频繁退出新建的,不说安全上,性能上损失也大
[解决办法]
楼主的问题 我也曾经深深的纠结

既然你要在线程中创建共享资源,那么不建议使用TerminateThread。
多线程时 你要临界这些资源 加锁。 TerminateThread时,不知道在何处退出,锁可能就不匹配了,导致其他线程死等。

至于你前面提到的“对象”,可以使用“引用计数”的思想,有一个线程使用“对象”计数就加1,线程退出就减1。根据计数来判断是否需要创建新“对象”。

一点浅见,期待高手~~
[解决办法]
有很多种退出线程的方法,这些方法的被称做线程之间的消息传递、同步、共享等。

终止线程,可以向线程发送消息/信号,或者一个互斥量,或者改变内存中的变量等,来通知线程,当线程收到这些消息/信号后,先做一些处理,比如释放掉线程内的资源,保存线程的运行结果等,然后自己退出线程,并返回一个UINT值。

这些方法在《windows核心编程》中有详细的论述。

如果一定用TermminateThread,必须确保线程内的资源都被自动释放或者无须释放任何资源,可以考虑用smart pointer智能指针。但是用这个方法时线程不会返回任何值来告诉你结果。
[解决办法]
同级线程互相杀容易出问题,不好控制,那就创建一个上级管理者,下面提申请,上面择时执行。
[解决办法]
无非就是while检查全局变量,没事就睡在条件变量或者select上,要退出的时候改全局变量,然后唤醒就行了。
[解决办法]
哇,这个题有好几问呢,逐点回答吧:

1. 使用TerminateThread到底会导致哪些不良后果呢, 线程是否在TerminateThread执行结束后立即被杀死呢
我个人认为由于被杀死的线程不知道执行到何处, 可能会出现一些new了的资源、打开的句柄没有被释放, 不知道是否有其他坏处

这是显然的,微软是不建议使用的,可以查看TerminateThread API的说明,试想一下用TerminateThread去终止一个拥有10个线程、3个临界区、3个事件触发器、5个动态数组、打开了3个文件的程序吧,其后果谁也说不清楚是什么,很有可能是灾难性的。

如果一定用TermminateThread,必须要知道你在做什么,确保线程内的资源都被自动释放或者无须释放任何资源,可以考虑用smart pointer智能指针。但是用这个方法时线程不会返回任何值来告诉你结果。

2. 其他一些语言中封装好的线程类例如java中的interrupt是否也存在这个问题


java会自动回收资源,但是上述其他问题仍然存在。

3. 我现在遇到的问题是否都是因为主、分线程访问同一对象导致的(其实就相当于全局变量带来的危害一样), 是否应该完全避免

不同线程/进程访问同一对象是无法避免的,并且是线程/进程的主要用途之一,但是需要一些线程同步的手段,例如互斥量、临界区、信号量等做一些限制,等待一个线程读/写完之后另一个线程再进行读/写,这些方法在《windows核心编程》中有详细的论述。

4. 大家在程序设计的时候一般都是怎么解决在一个线程中结束另一个线程的
终止线程,可以向线程发送消息/信号,或者一个互斥量,或者改变内存中的变量等,来通知线程,当线程收到这些消息/信号后,先做一些处理,比如释放掉线程内的资源,关闭打开的文件,释放所有的临界区互斥量,保存线程的运行结果等,然后自己退出线程,并返回一个UINT值。

这些方法在《windows核心编程》中有详细的论述。
[解决办法]
深受启发,学习了。
[解决办法]
例子能再具体点就好了
[解决办法]
我觉得下载和解压这两个工作应该分开,下载是通信的功能,是用来接收数据,至于收到的是什么内容通信部分并不关心。
通信部分只管下载,然后下载完成了,将下载文件的位置保存到一个列表A中,给出消息通知。如果都下载完成了,就等待新的下载任务。

解压部分只管从位置列表A中取文件,解压,完成后给出减压位置,发出消息通知。如果列表A为空,就等待。
这样做可以最大限度的利用线程,不用总是创建,释放,可以到程序结束的时候一次释放就可以了。从结构上来说也比较好处理。

[解决办法]
多线程协作中,如果出现大量共享对象以及交互操作.那应该考虑一下设计是不是有问题.
一般来说,需要多线程协作的系统中,每个工作对象应该保持相当的独立性.
如果需要响应中止消息,那工作对象的处理逻辑里就必须要有相应的响应机制.比如在设计时把任务的粒度做得很小,然后每次任务前都处理中止逻辑.
除非线程代码是经过特殊设计的(比如线程代码保证不使用堆,只使用栈;只使用特定的全局系统对象;不直接和其它任务交互等等),否则就不应该强制中止.
要想能强制中止线程还不出错,没有泄露,那就必须实现相应的垃圾回收机制.在中止线程后,对线程的资源进行扫描回收.

>主线程的逻辑是很有可能在杀死分线程后又建立一个分线程
按楼主这句话来看,你很可能是需要中止一个任务,再新开另一个任务.而这两个任务之间又有很大的耦合性.这应该是个设计缺陷.其实有很多改进方案可以选,一是让任务处理代码响应中止事件,但这样会影响一点性能,而且代码的复杂度可能会比较高.二是减少任务之间的耦合性.把任务的逻辑做成 接受任务->处理任务->提交结果 这种模式.当要中止任务时,直接废弃提交过程就可以了.这样的好处是逻辑简单,0响应时间.但当要中止任务时,要做无用的处理动作,白白消耗系统资源.三是结合前两种模式,找出两种方式的折中点,以达到最佳性能,最简代码.
[解决办法]
if not testThread.Suspended then
testThread.Suspend;
testThread.Terminate;
TerminateThread(testThread.Handle, 0);
FreeAndNil(testThread);
[解决办法]
我知道楼主的需求了,你可以参考apue P331页, 你可以在不能被中断的代码段pthread_setcancelstate设置不接受取消,等你的代码段完整处理完一个请求后再次pthread_setcancelstate恢复取消,其他现成调用pthread_cancel则不会让你的处理逻辑半路终止,而是在合适的时间窗口退出.


[解决办法]
我也正在纠结这个问题…比如作家读者问题,这里的读者是取出作品花费一定时间(较长)去阅读。现在作家更新作品,希望某个读者停止正在阅读的作品,而去获取最新的作品重新开始阅读。我用Qt,想通过信号与槽来实现,但是想不通这个停止的操作怎么去做?
就是停止这个操作能不能在读者进程还在跑函数的时候进行,读者进程什么时候才能对收到的信号进行响应?
有考虑过新开一个线程监视信号状态,然后根据信号终结掉某个读者进程,但是这样会引入很多错误

读书人网 >C++

热点推荐