昨天专家建议在线程执行函数中使用“while not ended do begin ...”来检查线程终止属性并从内部优雅地退出线程。我们刚刚测试了代码,但它仍然无法终止线程。但是这个线程可以通过外部调用TerminateThread函数实际终止。执行函数或执行函数中的大循环中有一些缺陷吗?或者在使用未终止循环时是否有特殊要求?
顺便说一句,endthread,exitthread和terminatethread之间有什么区别?怎么用?哪个比较好?
再次感谢你的帮助。
答案 0 :(得分:9)
如果while not Terminated do
没有足够快地终止线程,那么每次迭代完成的工作太多了(也就是说,很少检查循环条件not Terminated
),或者你有“意外地“在这个循环之后放了很多代码。
当然,如果你有一个反复运行循环的线程,直到终止,那么你应该while not Terminated do
。通常,一次迭代在短时间内完成(按每秒1到10000次迭代的顺序?),因此经常检查循环条件(每秒1到10000次)。但是如果你的线程不包含这样的循环,那么当然,将整个Execute
主体放在while not Terminated do
内对你没用。
不可强>
procedure TMyThread.Execute;
begin
inherited;
while not Terminated do
ComputeTheNextTenDigitsOfPi; // Takes 100 ms.
end;
<强>为强>
procedure TMyThread.Execute;
begin
inherited;
while not Terminated do
ComputeAVeryVeryLargeFractal; // Takes an hour.
// And you will create the same fractal
// over and over again.
end;
答案 1 :(得分:8)
如果您必须终止作业 - 例如,因为它在您无法控制的代码中被阻止 - 那么考虑尝试将其完全包装在一个单独的可执行文件中,并将其作为一个单独的可执行文件运行子流程,并在需要停止时终止流程。进程具有比线程更强的隔离。终止一个线程是一个肯定的痛苦方法 - 如果被终止的线程在内存管理器或某个类似的地方持有锁定怎么办?下次尝试分配内存(或类似内存)时,您的应用程序将陷入僵局!
答案 2 :(得分:5)
CodeInChaos
在评论中提供了一些很好的建议 - 在极少数情况下,线程应该从外部终止。
某些线程环境具有取消功能,您可以在其中取消(而不是终止)某个线程,并且在准备好时自行终止。这允许线程为何时安全终止设置自己的规则。
外部查杀的问题是目标线程可能具有资源锁定,现在永远不会释放,从而导致潜在的死锁。或者,即使在线程退出时释放资源,该资源中的数据也可能不再一致。
遵循的基本规则是所有线程必须检查是否应及时终止它们。换句话说,如果您正在等待工作,请在循环中经过几秒钟后超时并检查状态:
do while not terminating:
wait 2 seconds for work
if not terminating and work available:
do it
设置terminating
标志后,该特定线程永远不会超过约两秒钟退出。
并且,如果do it
是一个长期运行的任务,您可能还想定期检查,如果您也应该退出。