当我试图终止在单独线程上运行的长时间运行的进程时,我遇到了问题。
程序如下。WorkOne创建一个子进程,并运行一个长时间运行的进程"adb logcat",生成日志行。我在main()中启动WorkOne,等待5秒并尝试停止它。多次运行产生多个输出
import threading
import time
import subprocess
import sys
class WorkOne(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
self.event = threading.Event()
self.process = subprocess.Popen(['adb','logcat'], stdout=subprocess.PIPE, stderr=sys.stdout.fileno())
def run(self):
for line in iter(self.process.stdout.readline,''):
#print line
if self.event.is_set():
self.process.terminate()
self.process.kill()
break;
print 'exited For'
def stop(self):
self.event.set()
def main():
print 'starting worker1'
worker1 = WorkOne()
worker1.start()
print 'number of threads: ' + str(threading.active_count())
time.sleep(5)
worker1.stop()
worker1.join(5)
print 'number of threads: ' + str(threading.active_count())
if __name__ == '__main__':
main()
有时我得到[A]:
starting worker1
number of threads: 2
number of threads: 2
exited For
有时我得到[B]:
starting worker1
number of threads: 2
number of threads: 1
exited For
[C]:
starting worker1
number of threads: 2
number of threads: 2
我认为我应该期望得到[B]所有的时间。这里出了什么问题?
我认为[B]只有在子进程花费少于10秒的情况下才有可能:主线程休眠5秒,之后worker
在join()
的5秒超时内完成。
即使在join()
调用之后,worker
也可以存活10秒或更长时间,因为它有一个超时参数,这可能发生也可能不发生。然后你可以得到[A](子进程几秒钟后完成)或[C](子进程完成得很晚)。
要获得always [B],请删除join()
的timeout参数,以便主线程等待worker
完成(或者通过在循环外放置kill调用确保在10秒内终止进程)。
变化
if self.event.is_set():
self.process.terminate()
self.process.kill()
break;
if self.event.is_set():
self.process.terminate()
self.process.wait()
break
分号表明这里有问题。
我猜,没有wait()
线程有时解锁work1.join(5)
太快。在这些情况下,threading.active_count()
返回2。
,为@A。Rodas说,work1.join(5)
应该是work1.join()
,以确保连接在work1
完成之前不会解除阻塞。
顺便说一下,我不确定为什么你想要连续调用terminate
然后kill
。在Unix上,kill是一种更严重的终止形式。在Windows上,它们是相同的。因此,如果你要调用kill,就不需要调用terminate。
既然你知道subprocess
调用的程序,你也应该知道terminate是否足以停止它。
因此,您应该只需要一个:self.process.terminate()
或self.process.kill()
。